It's a feature ... albeit not very desirable.
When you do val (a,b,c) = tuple
, it is actually a pattern match:
tuple match {
case (a,b,c) => ...
}
Now, this statement above extracts three values from tuple using unapply
, and assigns them to a, b, and c. But this:
tuple match {
case (1, 2, 3) => ...
}
Does something different. It extracts the three values from the tuple, and compares them to the three values on the left-hand-side. What if you wanted to match against a variable:
val foo = 1
val bar = 2
val bat = 3
tuple match {
case(foo, bar, bat) => ...
}
This will not work: this case is exactly the same as the first one, and will do exactly the same thing: it will extract the values from the tuple into three (new) local variables without any matching. But what if you wanted to match the variables? How to get around this? There are two ways: you can enclose the variable names into backticks or you make the names start with a captial letter:
val Foo = 1
val bar = 2
var baz = 3
tuple match {
case(Foo, `bar`, `bat`) => ...
}
To summarize: tuple match { case (foo, _) =>
means "extract the first element from tuple and assign to a new variable foo
. tuple match { case (Foo, _)
means "execute this case
if the first element of tuple is equal to the value of an existing variable Foo
".
"Assignments" follow the same logic (because they aren't really "assignments" so much as just another syntax for pattern match), so, when you say val (a,b,c,d,E) = r
, it means "assign the first four elements of r
to the new variables, and match the last element against existing variable E
". But E
does not exist, thus the error.