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

2

6

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?

Lizalizabeth answered 2/4, 2016 at 0:57 Comment(0)
N
5

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.

Nasya answered 2/4, 2016 at 1:19 Comment(2)
Is there any way to get around this and do what OP wants to do, assigning the value to a variable starting with a capital letter? Like the opposite of backticks?Unhinge
@LuigiPlinge not that I know off ... other than something like val (a, b) = tuple; val B = bNasya
E
4

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.

Elusion answered 2/4, 2016 at 6:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.