Jeff
Jeff

Reputation: 149

Pattern matching :: case class

Looking at the source code for immutable.List, I see this

final case class ::[B](override val head: B,
                       private[scala] var tl: List[B]) extends List[B] {
    override def tail : List[B] = tl
    override def isEmpty: Boolean = false
}

My understanding of case classes is that this signature is invalid because:

Can somebody explain to me how this is working?

Upvotes: 1

Views: 159

Answers (2)

Dima
Dima

Reputation: 40500

Your assumptions are missing "by default". By default constructor parameters are vals and public. I.e., if you say case class Foo(bar: String), that'll make bar a val and public. Doesn't mean, you can't still say case class Foo(private var bar: String)

Upvotes: 1

0__
0__

Reputation: 67280

It is not forbidden that constructor parameters are non-public. The extractor will still work. The reason it was made package-private is exactly because it is a variable, and so the user cannot alter the value (but only read it through the tail method). Again this is not forbidden, but just generally strongly discouraged. You should not normally use a var because the case-class' equality and hash-code depend on the constructor arguments.

List uses a var here simply to make it easier to assemble new lists. If you look at the source code, you can see this for example in the take method. And you can also see that tl is assigned only internally during the construction of new lists. Once they are returned, that variable is not touched any longer, and therefore equality is not broken.

Upvotes: 3

Related Questions