val 1 = 2 compiles

477 views
Skip to first unread message

Aleksey Nikiforov

unread,
Aug 23, 2011, 11:05:37 AM8/23/11
to scala-user
Surprisingly, the following compiles. However it does not produce a
val `1` but generates strange bytecode.

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

The def version does not compile.

scala> object Foo { def 1 = 100 }
<console>:1: error: identifier expected but integer literal found.
object Foo { def 1 = 100 }
^

Is this a bug or am I missing something?

Seth Tisue

unread,
Aug 23, 2011, 11:22:09 AM8/23/11
to scala-user
On Tue, Aug 23, 2011 at 11:05 AM, Aleksey Nikiforov <lex...@gmail.com> wrote:
> Surprisingly, the following compiles. However it does not produce a
> val `1` but generates strange bytecode.
>
> scala> object Foo { val 1 = 100 }
> defined module Foo

BEST BUG EVER!!!

More fun:

scala> object O { val 1 = 2; def x = 1 }
defined module O

scala> O.x
scala.MatchError: 2 (of class java.lang.Integer)

--
Seth Tisue | Northwestern University | http://tisue.net
lead developer, NetLogo: http://ccl.northwestern.edu/netlogo/

Daniel Sobral

unread,
Aug 23, 2011, 11:27:57 AM8/23/11
to Seth Tisue, scala-user
Just tell me what's the ticket, so I can add it to my favorites. :-)

--
Daniel C. Sobral

I travel to the future all the time.

Aleksey Nikiforov

unread,
Aug 23, 2011, 11:47:19 AM8/23/11
to Daniel Sobral, Seth Tisue, scala-user

Lars Hupel

unread,
Aug 23, 2011, 1:53:33 PM8/23/11
to scala...@googlegroups.com

I don't see why that's a bug. The statement `val 1 = 2` is actually a
pattern match and roughly corresponds to

2 match { case 1 => ... }

Also, I don't understand to what kind of "shadowing" you refer to. The
MatchError occurs on `O.x` because objects are initialized lazily, and
the initialization is atomic. That means that on calling `O.x`, `O` is
initialized, thus the above pattern match is executed, yielding the
mentioned MatchError. Seems pretty much like behaviour as specified to me.

Aleksey Nikiforov

unread,
Aug 23, 2011, 1:59:10 PM8/23/11
to Lars Hupel, scala...@googlegroups.com
I am struggling to understand how that becomes a pattern match.
Clearly this is an not intuitive behavioral. Could you elaborate on
how exactly it becomes a pattern match and where this behavior could
be useful.

Lars Hupel

unread,
Aug 23, 2011, 2:06:58 PM8/23/11
to scala...@googlegroups.com
The thing you write between `val` and `=` is in most cases just a plain
name of a variable, for example `val x = foo`. Actually, `x` is a bit
more than just a name, as it can be a pattern. Consider the similarity
between:

foo match { case x => doStuff(x) }

and

val x = foo
doStuff(x)

Everything (apart from `|`) which is allowed after `case` is also
allowed after `val` and is translated to a pattern match (at least as
far as I know).

Another example:

val (a, b) = (1,2)
println(a)
println(b)

vs.

(1, 2) match { case (a, b) =>
println(a)
println(b)
}

Both will produce exactly the same output, and I suspect the generated
byte code is also similar.

Now, as constants, or in this case, literals, are allowed in pattern
matches, they are also allowed in `val` definitions.

2 match { case 1 => }

vs.

val 1 = 2

Hope that helps. I agree with you that this might be confusing for
newcomers, but I think this behaviour should be kept for the sake of
symmetry.

HamsterofDeath

unread,
Aug 23, 2011, 2:11:45 PM8/23/11
to scala...@googlegroups.com
if 1 = 2 becomes a match, what's the name of the val? is it nameless?

Lars Hupel

unread,
Aug 23, 2011, 2:17:58 PM8/23/11
to scala...@googlegroups.com
> if 1 = 2 becomes a match, what's the name of the val? is it nameless?

There will be no val after that, as no identifier is specified.

Interestingly enough, I think there is a small asymmetry between pattern
matching and val definitions:

val F = 1

produces a new variable called `F` with value 1, whereas

1 match { case G => }

fails to compile with "error: not found: value G" (because in `case`
patterns upper case identifiers don't introduce a variable but rather
match against an existing one or an extractor).

Kevin Wright

unread,
Aug 23, 2011, 2:31:07 PM8/23/11
to Lars Hupel, scala...@googlegroups.com
Yet:

scala> val (X,Y) = (1,2)
<console>:7: error: not found: value X
<console>:7: error: not found: value Y


So it looks to be just that particular degenerate case where the two forms differ. Makes sense really, how else could we create uppercased values?

--
Kevin Wright
mail: kevin....@scalatechnology.com
gtalk / msn : kev.lee...@gmail.com
vibe / skype: kev.lee.wright
steam: kev_lee_wright

"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra

Lars Hupel

unread,
Aug 23, 2011, 2:32:41 PM8/23/11
to scala...@googlegroups.com
> So it looks to be just that particular degenerate case where the two forms
> differ. Makes sense really, how else could we create uppercased values?

Maybe with

val `G` = 1

which would be quite inconvenient I guess.

Seth Tisue

unread,
Aug 23, 2011, 2:37:57 PM8/23/11
to scala...@googlegroups.com
>> Filed the ticket: https://issues.scala-lang.org/browse/SI-4939
>
> I don't see why that's a bug. The statement `val 1 = 2` is actually a
> pattern match

Well damn. I'd feel worse for missing that if I weren't in such
illustrious company (Lex, Daniel).

It is both delicious and repellent. Scala is either to be lauded, or chided.

No-variable val definitions are even explicitly speced. See SLS 4.1:
"If p has no bound variables..." What is the purpose of allowing
this...? (I'm trying to keep an open mind.)

Surely it's a REPL bug, though that only one of the following produces an error:

scala> val 1 = 2

scala> { val 1 = 2 }


scala.MatchError: 2 (of class java.lang.Integer)

If the former had errored in the REPL, I would have known right away
that a pattern match was involved.

Razvan Cojocaru

unread,
Aug 23, 2011, 2:46:21 PM8/23/11
to Seth Tisue, scala...@googlegroups.com
scala> object x { val 1=2 }
defined module x

scala> object x { val a@1=2 }
defined module x

scala> x.a


scala.MatchError: 2 (of class java.lang.Integer)

at x$.<init>(<console>:7)
at x$.<clinit>(<console>)
at .<init>(<console>:9)
at .<clinit>(<console>)
at .<init>(<console>:11)
at .<clinit>(<console>)
at $export(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39
)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl
.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:592)
at
scala.tools.nsc.interpreter.IMain$Request$$anonfun$10.apply(IMain.scala:828)
at
scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43)
at scala.tools.nsc.io.package$$anon$2.run(package.scala:31)
at java.lang.Thread.run(Thread.java:662)

Lars Hupel

unread,
Aug 23, 2011, 2:48:29 PM8/23/11
to scala...@googlegroups.com
> Surely it's a REPL bug, though that only one of the following produces an error:
>
> scala> val 1 = 2
>
> scala> { val 1 = 2 }
> scala.MatchError: 2 (of class java.lang.Integer)
>
> If the former had errored in the REPL, I would have known right away
> that a pattern match was involved.

Yay, yet another new aspect in this story :)

The former prints

scala> val 1 = 2

<console>:8: error: value x$1 is not a member of object $iw
`x$1`

which indicates that after the REPL is done with its REPL magic and
hands the string containing the statement (amongst other things) to the
compiler, it fails with an error, thus preventing the statement to be
executed at all. This is why no MatchError is thrown there.

What is more interesting is that the REPL thinks `1` is actually an
identifier, which qualifies as a bug imho.

Razvan Cojocaru

unread,
Aug 23, 2011, 2:52:25 PM8/23/11
to Lars Hupel, scala...@googlegroups.com, Seth Tisue
Not quite...

In my example, x.a failed only when evaluated... that explains the Seth
example as well - the {} forced evaluation to return a value...

scala> object x { val a@1=2 }
defined module x

scala> x.a


scala.MatchError: 2 (of class java.lang.Integer)

does this mean that all matches are lazy?

For me the val 1=2 also fails with the same error though.

-----Original Message-----
From: scala...@googlegroups.com [mailto:scala...@googlegroups.com] On

Lars Hupel

unread,
Aug 23, 2011, 2:50:11 PM8/23/11
to scala...@googlegroups.com
> scala> object x { val 1=2 }
> defined module x
>
> scala> object x { val a@1=2 }
> defined module x
>
> scala> x.a
> scala.MatchError: 2 (of class java.lang.Integer)
> at x$.<init>(<console>:7)
> at x$.<clinit>(<console>)
> at .<init>(<console>:9)
> at .<clinit>(<console>)
> at .<init>(<console>:11)
> [snip]

So? The only difference between those two statements is that in the
second one, the name `a` is bound to `1`, which can be eliminated as no
one accesses `a`.

Lars Hupel

unread,
Aug 23, 2011, 2:58:22 PM8/23/11
to scala...@googlegroups.com
> Not quite...
>
> In my example, x.a failed only when evaluated... that explains the Seth
> example as well - the {} forced evaluation to return a value...
>
> scala> object x { val a@1=2 }
> defined module x
>
> scala> x.a
> scala.MatchError: 2 (of class java.lang.Integer)
>
> does this mean that all matches are lazy?
>
> For me the val 1=2 also fails with the same error though.

I'm not sure whether I'm following. In *this* example, it fails on the
first access because *objects* are lazy.

Seth's first example without {} produces a compile error in the REPL
(not expected).

Seth's second example with {} produces an immediate MatchError as you
correctly said (as I expected).

Typing `val a@1 = 2` directly in the REPL throws a MatchError (also as
expected).

Razvan Cojocaru

unread,
Aug 23, 2011, 3:28:51 PM8/23/11
to Lars Hupel, scala...@googlegroups.com
What do you mean?

scala> object x { val a@1=2 }
defined module x

scala> x.`1`
<console>:9: error: value 1 is not a member of object x
x.`1`
^

scala>

ALSO

scala> object y { val a@b=2 }
defined module y

scala> y.a
res1: Int = 2

scala> y.b
res2: Int = 2

scala>

------

It's not that simple :)
... using 1 was just a coincidence - it's not interpreted as a label...

scala> val 5=6


<console>:8: error: value x$1 is not a member of object $iw
`x$1`

^

scala>
-----

ABOUT lazy objects - indeed, mea culpa!

----


-----Original Message-----
From: scala...@googlegroups.com [mailto:scala...@googlegroups.com] On

Lars Hupel

unread,
Aug 23, 2011, 3:34:52 PM8/23/11
to scala...@googlegroups.com
> scala> object x { val a@1=2 }
> defined module x
>
> scala> x.`1`
> <console>:9: error: value 1 is not a member of object x
> x.`1`

Let me proceed by analogy:

2 match {
case a@1 => println(a)
}

compiles whereas

2 match {
case a@1 => println(`1`)
}

doesn't.

> scala> object y { val a@b=2 }
> defined module y
>
> scala> y.a
> res1: Int = 2
>
> scala> y.b
> res2: Int = 2

2 match {
case a@b => println(a); println(b)
}

also compiles fine.

`foo@bar` binds the value matched against `bar` to the identifier `foo`.

> It's not that simple :)

> .... using 1 was just a coincidence - it's not interpreted as a label...


>
> scala> val 5=6
> <console>:8: error: value x$1 is not a member of object $iw
> `x$1`

No idea about that one.

Naftoli Gugenheim

unread,
Aug 23, 2011, 7:23:43 PM8/23/11
to Razvan Cojocaru, Lars Hupel, scala...@googlegroups.com
On Tue, Aug 23, 2011 at 3:28 PM, Razvan Cojocaru <p...@razie.com> wrote:
What do you mean?

scala> object x { val a@1=2 }
defined module x

scala> x.`1`
<console>:9: error: value 1 is not a member of object x
      x.`1`
        ^


Because it doesn't compile, x is never initialized.

This illustrates it:


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

scala> x                    
scala.MatchError: 2
        at x$.<init>(<console>:5)
        at x$.<clinit>(<console>)
        at .<init>(<console>:7)
        at .<clinit>(<console>)
        at RequestResult$.<init>(<console>:9)
        at RequestResult$.<clinit>(<console>)
        at RequestResult$scala_repl_result(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$17.apply(Interpreter.scala:988)
        at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$17.apply(Interpreter.scala:988)
        at scala.util.control.Exception$Catch.ap...
scala> 

So all you need to do to get the MatchError is initialize x.

Razvan Cojocaru

unread,
Aug 23, 2011, 11:31:01 PM8/23/11
to Naftoli Gugenheim, Lars Hupel, scala...@googlegroups.com
Diaconnect here... that's not what I meant :). The compiler correctly figures out that 1 is a constant and does not try to make it a label, that's what I meant. 

Also - in fact it is compiled, just never executed. The compiler would have known about x.1 if 1 became a label, that's what a@b was showing. 

Thanks,
Razvan

Daniel Sobral

unread,
Aug 24, 2011, 10:01:43 AM8/24/11
to Seth Tisue, scala...@googlegroups.com
On Tue, Aug 23, 2011 at 15:37, Seth Tisue <se...@tisue.net> wrote:
>>> Filed the ticket: https://issues.scala-lang.org/browse/SI-4939
>>
>> I don't see why that's a bug. The statement `val 1 = 2` is actually a
>> pattern match
>
> Well damn. I'd feel worse for missing that if I weren't in such
> illustrious company (Lex, Daniel).

For whatever it is worth, I always thought that pattern matching on
"val" only applied if you added parenthesis, since "val X = 2" is
valid. Turns out it was an invalid assumption.

For that matter, pattern matching is _not_ the same among the three
places where it happens. We have "val X" being different than "case
X", and for (pat <- ...) does something different than both val and
match. Also, doesn't accept the same patterns -- for (x: Int <- ...)
is not valid, for instance.

Which is a bunch of excuses for not realizing what was going on. :-)
The error message was a bit deceiving as well, with that printing of
"2".

Razvan Cojocaru

unread,
Aug 24, 2011, 10:12:06 AM8/24/11
to Daniel Sobral, Seth Tisue, scala...@googlegroups.com
Why do you think val x=2 is different than case x?

scala> 2 match {
| case 1 => {}


| }
scala.MatchError: 2 (of class java.lang.Integer)

at .<init>(<console>:8)


at .<clinit>(<console>)

ALSO
scala> for (x:Int <- 0 to 2) println(x)
0
1
2

BUT MORE INTERESTINGLY

scala> for (1 <- 0 to 2) println ("match... who?")
match... who?

scala>


COOL, HUH?

-----Original Message-----
From: scala...@googlegroups.com [mailto:scala...@googlegroups.com] On

Daniel Sobral

unread,
Aug 24, 2011, 10:25:40 AM8/24/11
to Razvan Cojocaru, Seth Tisue, scala...@googlegroups.com
On Wed, Aug 24, 2011 at 11:12, Razvan Cojocaru <p...@razie.com> wrote:
> Why do you think val x=2 is different than case x?

scala> 2 match { X => true }
<console>:1: error: 'case' expected but identifier found.
2 match { X => true }
^

scala> val X = 2
X: Int = 2


>
> scala> 2 match {
>     | case 1 => {}
>     | }
> scala.MatchError: 2 (of class java.lang.Integer)
>        at .<init>(<console>:8)
>        at .<clinit>(<console>)
>
> ALSO
> scala> for (x:Int <- 0 to 2) println(x)
> 0
> 1
> 2
>
> BUT MORE INTERESTINGLY
>
> scala> for (1 <- 0 to 2) println ("match... who?")
> match... who?

Yes, but,

scala> for (x <- List(1, 'a, 'b')) x match { case y: Int => println(y)
case _ => }
1

scala> for (y: Int <- List(1, 'a, 'b')) println(y)
<console>:8: error: type mismatch;
found : Int => Unit
required: Any => ?
for (y: Int <- List(1, 'a, 'b')) println(y)
^

So, as you see, not all patterns are equal.

Daniel Sobral

unread,
Aug 24, 2011, 10:28:00 AM8/24/11
to Razvan Cojocaru, Seth Tisue, scala...@googlegroups.com
On Wed, Aug 24, 2011 at 11:12, Razvan Cojocaru <p...@razie.com> wrote:
> Why do you think val x=2 is different than case x?

Oops, posted incorrect code. Again:

scala> 2 match { case X => true }
<console>:8: error: not found: value X
2 match { case X => true }
^

scala> val X = 2
X: Int = 2

scala> 2 match { case `an example` => true }
<console>:8: error: not found: value an example
2 match { case `an example` => true }
^

scala> val `an example` = 2
an example: Int = 2

Razvan Cojocaru

unread,
Aug 24, 2011, 10:45:24 AM8/24/11
to Daniel Sobral, Seth Tisue, scala...@googlegroups.com
WTF?

scala> 2 match { case razvan => true }
res11: Boolean = true

scala> 2 match { case RAZVAN => true }
<console>:8: error: not found: value RAZVAN
2 match { case RAZVAN => true }
^

scala> 2 match { case `RAZVAN` => true }
<console>:8: error: not found: value RAZVAN
2 match { case `RAZVAN` => true }
^

scala>

Vlad Patryshev

unread,
Aug 24, 2011, 10:47:46 AM8/24/11
to Razvan Cojocaru, Daniel Sobral, Seth Tisue, scala...@googlegroups.com
Wow...

for (x@List(a,b) <- List(0,1,"Z",(5,6),List("x", "y"))) {print("wow: " + x)}

Thanks,
-Vlad

Razvan Cojocaru

unread,
Aug 24, 2011, 10:54:14 AM8/24/11
to Daniel Sobral, scala...@googlegroups.com
More WTF

scala> 2 match { case `razvan` => true }

<console>:8: error: not found: value razvan


2 match { case `razvan` => true }

^

scala> 2 match { case razvanc => true }
res17: Boolean = true

it's clearly a syntax issue in the parser?

Jason Zaugg

unread,
Aug 24, 2011, 11:25:04 AM8/24/11
to Razvan Cojocaru, Daniel Sobral, scala...@googlegroups.com

In a pattern, a capitalized identifier or a backtick quoted identifier
refers to a previously defined stable identifier (ie, a val). A
lowercase identifier introduces a new variable binding.

-jason

Razvan Cojocaru

unread,
Aug 24, 2011, 11:28:39 AM8/24/11
to Jason Zaugg, Daniel Sobral, scala...@googlegroups.com
So... That's what's wrong with the parser then!

;)

Thanks,
Razvan

Stefan Wagner

unread,
Aug 27, 2011, 11:28:02 AM8/27/11
to scala...@googlegroups.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Am 23.08.2011 17:05, schrieb Aleksey Nikiforov:
> Surprisingly, the following compiles. However it does not produce a
> val `1` but generates strange bytecode.
>
> scala> object Foo { val 1 = 100 }

I guess it is related:

object Foo { val _ = 100 }

but I have no idea what to do with it.

- --

Tsch���--->...Stefan
- ---------------------------
Don't visit my homepage at:
http://home.arcor-online.net/hirnstrom
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk5ZDQEACgkQQeATqGpDnRoJJACfeostKnegxI1rRD6cOmN7ZLLr
LaAAmwWCfLsPBzZbAt3eb6s3JesX1pWa
=SjJJ
-----END PGP SIGNATURE-----

Reply all
Reply to author
Forward
0 new messages