Does Scala give a compile-time error when assigning a value to a numeric literal?

During scala training, I came across the following weird 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 the compiler to throw an error on val 2 = 123 , because identifiers should not start with a number, but the code compiles without warning. However, at runtime, it throws an exception immediately:

An exception is thrown in the main thread java.lang.ExceptionInInitializerError at temptests.TempTest.main (TempTest.scala) in sun.reflect.NativeMethodAccessorImpl.invoke0 (native method) in sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethplod.Implj.Iml sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) in java.lang.reflect.Method.invoke (Method.java:498) in com.intellij.rt.execution.application.AppMain.main (AppMain.java: 144) Called: scala.MatchError: 123 (class java.lang.Integer) in temptests.TempTest $. (TempTest.scala: 5) at temptests.TempTest $. (TempTest.scala) ... 6 more

I'm just wondering: how is val 2 = 123 understood by scala ? Why is there no compile-time error?

+8
scala runtime-error
source share
2 answers

I'm just wondering: how is val 2 = 123 understood by Scala?

You can think of val 2 = 123 as:

 123 match { case 2 => 2 } 

Part of the variable name in Scala is not always a simple name; it can also be a template , for example:

 val (x, y) = (1, 2) 

Decomposes 1 and 2 by x and y, respectively. In scala, everything that is allowed after the case statement is also allowed after val and is converted to match the pattern.

From the specification (highlighted by me):

Value definitions may alternatively have a pattern as the left side. If p is some pattern other than a simple name or a name followed by a colon and type, then the definition of val p = e expanded as follows:

(transition to the corresponding example):

If p has a single bound variable x:

 val x = e match { case p => x } 

It is for this reason that the compiler does not emit a compile-time error. There is a lengthy discussion of the topic on this issue of the google group.

+12
source share

The left side of the val declaration may be a template. 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 mainly used to extract tuples into readable local vals:

 val test = ("Foo", 30) val (name, age) = test 
+3
source share

All Articles