在scala中发出`object Foo {val 1 = 2}`

时间:2011-08-24 14:04:58

标签: scala methods

我发现了scala的这个问题:https://issues.scala-lang.org/browse/SI-4939

似乎我们可以定义一个名称为数字的方法:

scala> object Foo { val 1 = 2 }
defined module Foo

但我们无法援引它:

scala> Foo.1
<console>:1: error: ';' expected but double literal found.
       Foo.1

我们可以在对象中调用它:

scala> object O { val 1 = 1; def x = 1 }
defined module O
scala> O.x
res1: Int = 1

然后将抛出错误:

scala> object O { val 1 = 2; def x = 1 }
defined module O
scala> O.x
scala.MatchError: 2
    at O$.<init>(<console>:5)
    at O$.<clinit>(<console>)
    at .<init>(<console>:7)
    at .<clinit>(<console>)
    at RequestResult$.<init>(<console>:9)

我使用scalac -Xprint:typer查看代码,val 1 = 2部分是:

<synthetic> private[this] val x$1: Unit = (2: Int(2) @unchecked) match {
    case 1 => ()
}

从中我们可以看到方法名称已更改为x$1,并且只能在该对象内调用。

该问题的解决方案是:无法修复

我想知道是否有理由允许数字作为方法的名称?有什么情况我们需要使用“数字”方法吗?

4 个答案:

答案 0 :(得分:10)

此处没有绑定名称“1”。 val 1 = 2是模式匹配表达式,与val (x,2) = (1,2)x绑定到1的方式大致相同(如果第二个元素不相同,则会抛出MatchError。这是允许的,因为没有真正的理由来添加特殊情况来禁止它;这种方式val模式匹配(几乎)与match模式匹配完全相同。

答案 1 :(得分:4)

这种决定通常有两个因素:

  1. Scalac中存在许多优先级较高的错误,并且错误修复资源有限。此行为是良性的,因此优先级较低。

  2. 语言规范的复杂性增加会带来长期成本,而且当前的行为与规范一致。一旦事情开始变得特殊,就会出现雪崩效应。

  3. 这是这两者的一些组合。


    更新。这对我来说似乎很奇怪:

    val pair = (1, 2)
    object Foo
    object Bar
    
    val (1, 2) = pair     // Pattern matching on constants 1 and 2
    val (Foo, Bar) = pair // Pattern matching on stable ids Foo and Bar
    val (foo, bar) = pair // Binds foo and bar because they are lowercase
    val 1 = 1             // Pattern matching on constant 1
    val Foo = 1           // *Not* pattern matching; binds Foo
    

    如果val 1 = 1是模式匹配,那么为什么val Foo = 1绑定Foo而不是模式匹配?

    更新2 。 Daniel Sobral指出这是一个特殊的例外,而Martin Odersky最近wrote the same

答案 2 :(得分:1)

以下是一些示例,说明作业的LHS如何不仅仅是一个名称:

val pair = (1, 2)
val (a1, b1) = pair // LHS of the = is a pattern
val (1, b2) = pair // okay, b2 is bound the the value 2
val (0, b3) = pair // MatchError, as 0 != 1
val a4 = 1 // okay, a4 is bound to the value 1
val 1 = 1 // okay, but useless, no names are bound
val a @ 1 = 1 // well, we can bind a name to a pattern with @ 
val 1 = 0 // MatchError

答案 3 :(得分:0)

与往常一样,您可以使用反引号来逃避名称。我认为支持这些名称没有问题 - 要么你使用它们,它们适合你,要么它们不能为你工作,你就不会使用它们。