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?
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 C. Sobral
I travel to the future all the time.
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.
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.
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).
Maybe with
val `G` = 1
which would be quite inconvenient I guess.
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.
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)
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.
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
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`.
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).
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
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.
What do you mean?
scala> x.`1`
scala> object x { val a@1=2 }
defined module x
<console>:9: error: value 1 is not a member of object x
x.`1`
^
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".
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
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.
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
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>
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?
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
;)
Thanks,
Razvan
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-----