Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala bug or feature? Multiple assignment error with capital letter variables

Let's say function r returns tuple of five values.

scala> def r = (1,2,3,4,5)
r: (Int, Int, Int, Int, Int)

When I assign the returned value from r, I got error with capital letter variable.

scala> val (a,b,c,d,E) = r
<console>:13: error: not found: value E
       val (a,b,c,d,E) = r
                    ^

If I don't use the capital letter, no error occurs.

scala> val (a,b,c,d,e) = r
a: Int = 1
b: Int = 2
c: Int = 3
d: Int = 4
e: Int = 5

However, I can assign capital letter variable with single assignemnt.

scala> val Q = 10
Q: Int = 10

Is this a bug or feature of Scala?

like image 826
prosseek Avatar asked Apr 02 '16 00:04

prosseek


2 Answers

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.

like image 155
Dima Avatar answered Nov 09 '22 05:11

Dima


Its called Stable Identifiers . So whenever you use a upper case letter as a variable name (or at the start of a variable name) while doing a pattern match(which is happening in this case) the compiler thinks this is a constant value and hence goes to the behavior(comparing the two values E and 5 instead of assigning 5 to E).

Examples :

val (a,b,c,d,extsom) = r This will work.

val (a,b,c,d,Extsom) = r This will not.

like image 4
Som Bhattacharyya Avatar answered Nov 09 '22 05:11

Som Bhattacharyya