开发者

issue `object Foo { val 1 = 2 }` in scala

开发者 https://www.devze.com 2023-03-30 23:29 出处:网络
I found this issue of scala: https://issues.scala-lang.org/browse/SI-4939 Seems we can define a method whose name is a number:

I found this issue of scala: https://issues.scala-lang.org/browse/SI-4939

Seems we can define a method whose name is a number:

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

But we can't invoke it:

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

And we can invoke it inside the object:

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

And follow will throw error:

scala> object O { val 1 = 2; def x = 1 }
defined module O
sc开发者_JAVA百科ala> 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)

I use scalac -Xprint:typer to see the code, the val 1 = 2 part is:

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

From it, we can see the method name changed to x$1, and only can be invoked inside that object.

And the resolution of that issue is: Won't Fix

I want to know is there any reason to allow a number to be the name of a method? Is there any case we need to use a "number" method?


There is no name "1" being bound here. val 1 = 2 is a pattern-matching expression, in much the same way val (x,2) = (1,2) binds x to 1 (and would throw a MatchError if the second element were not thet same). It's allowed because there's no real reason to add a special case to forbid it; this way val pattern matching works (almost) exactly the same way as match pattern-matching.


There are usually two factors in this kind of decision:

  1. There are many bugs in Scalac that are much higher priority, and bug fixing resources are limited. This behavior is benign and therefore low priority.

  2. There's a long term cost to any increases in the complexity of the language specification, and the current behavior is consistent with the spec. Once things start getting special cased, there can be an avalanche effect.

It's some combination of these two.


Update. Here's what seems strange to me:

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

If val 1 = 1 is pattern matching, then why should val Foo = 1 bind Foo rather than pattern match?

Update 2. Daniel Sobral pointed out that this is a special exception, and Martin Odersky recently wrote the same.


Here's a few examples to show how the LHS of an assignment is more than just a name:

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


As always, you can use backticks to escape the name. I see no problem in supporting such names – either you use them and they work for you or they do not work for you, and you don’t use them.

0

精彩评论

暂无评论...
验证码 换一张
取 消