Scala在给数字文本赋值时没有编译时错误?

Scala在给数字文本赋值时没有编译时错误?,scala,runtime-error,Scala,Runtime Error,在学习scala时,我偶然发现了以下奇怪的片段: 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

在学习scala时,我偶然发现了以下奇怪的片段:

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")
  }
}
我希望编译器会在
val 2=123
上抛出一个错误,因为标识符不能以数字开头,但代码编译时没有警告。 但是,在运行时,它会立即引发异常:

线程“main”java.lang.ExceptionInInitializeError中的异常位于 诱惑。诱惑。主要(诱惑。斯卡拉)在 sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)位于 invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 位于java.lang.reflect.Method.invoke(Method.java:498) com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) 原因:scala.MatchError:123(属于java.lang.Integer类)位于 诱惑。诱惑美元(诱惑。斯卡拉:5)在 诱惑。诱惑美元。(诱惑。斯卡拉)。。。还有6个

我只是好奇:
val 2=123
是如何被
Scala
理解的?为什么没有编译时错误

我只是好奇:Scala是如何理解
val 2=123

您可以将
val 2=123
想象为:

123 match {
    case 2 => 2
}
Scala中的变量名部分并不总是一个简单的名称,它也可以是一种模式,例如:

val (x, y) = (1, 2)
将1和2分别分解为x和y。在scala中,case语句之后允许的所有内容也都在val之后允许,并被转换为模式匹配

(我的重点):

值定义也可以使用模式作为左侧。 如果p是某种模式,而不是一个简单的名称或名称后面跟一个 冒号和类型,则值定义
val p=e
展开为 如下:

(跳到相关示例):

如果p有唯一的绑定变量x:


这就是编译器不发出编译时错误的原因。这篇文章对这个主题进行了长时间的讨论。

声明的左侧可以是一种模式。看

所以

可以写成

123 match {
  case 2 => 2
}
这会导致匹配错误

在现实生活中,这主要用于将元组提取到可读的本地VAL:

val test = ("Foo", 30)
val (name, age) = test

我认为这场比赛必须是另一种方式,因为
2
是匹配的模式。感谢你们两位!这也说明了
val 2=2
工作正常的原因。然而,有没有任何例子表明在左边有一个文本而不是一个更一般的模式是有帮助的?@cubiclettuce想不出一个你真的想这样做的原因。我也不知道,但是如果真的没有用例,那么编译器最好在左边捕捉一个文本的特殊情况,因为它不能是任何有意义的,而且很可能是一个打字错误。但这实际上只是一个小问题,我只对理解“为什么”感兴趣。@cubiclettuce:编译器有太多这样的特殊情况是有害的,因为这样会使程序员更难学习底层规则。(也就是说,编译器警告是完全合理的。)我100%确定这是一个副本,但我一生都找不到!
123 match {
  case 2 => 2
}
val test = ("Foo", 30)
val (name, age) = test