While learning scala
I stumbled upon the following strange snippet:
package temptests
object TempTest {
//def 2 = 123 // does not compile
val 2 = 123 // compiles, but leads to an exception at runtime
def main(args: Array[String]) = { // just do something to load this class
println("Hello")
}
}
I would expect that the compiler would throw an error on val 2 = 123
because identifiers must not start with a digit, but the code compiles without a warning.
However, at runtime it immediately throws an Exception:
Exception in thread "main" java.lang.ExceptionInInitializerError at temptests.TempTest.main(TempTest.scala) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) Caused by: scala.MatchError: 123 (of class java.lang.Integer) at temptests.TempTest$.(TempTest.scala:5) at temptests.TempTest$.(TempTest.scala) ... 6 more
I am just curious: how is val 2 = 123
understood by Scala
? Why is there no compile-time error?
I am just curious: how is
val 2 = 123
understood by Scala?
You can think of val 2 = 123
as:
123 match {
case 2 => 2
}
The variable name part in Scala isn't always a simple name, it can also be a pattern, for example:
val (x, y) = (1, 2)
Will decompose 1 and 2 to x and y, respectively. In scala, everything which is allowed after a case statement is also allowed after val and is translated to a pattern match.
From the specification (emphasis mine):
Value definitions can alternatively have a pattern as left-hand side. If p is some pattern other than a simple name or a name followed by a colon and a type, then the value definition
val p = e
is expanded as follows:
(Skipping to the relevant example):
If p has a unique bound variable x:
val x = e match { case p => x }
This is the reason the compiler doesn't emit a compile time error. There is a lengthy discussion of the subject in this google group question.
The left hand side of a val
declaration can be a pattern. See scala language documentation.
so
val 2 = 123
can be written as
123 match {
case 2 => 2
}
which gives a match error.
In real life this is mostly used to extract tuples to readably local vals:
val test = ("Foo", 30)
val (name, age) = test
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With