Re: [scala-user] Re: val 1 = 2 compiles

67 views
Skip to first unread message

Francois

unread,
Aug 25, 2011, 5:06:01 AM8/25/11
to scala-debate
On 24/08/2011 16:01, Daniel Sobral wrote:
> 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".

Poor me who was thinking that Scala was less full of edge cases than
Java, but that one is a perfect counter example.

It seems to be a "feature" with a quite hight level of surprise, and a
really really small use case surface (well, if it is still surprising
among guys like Seth and Daniel today, well, it tells a lot).

The sole thing than a "val" may leads to such exception, without
warning, is quite deceptive. So, isn't this a perfect case for a
feature removal, or at least a syntax change ? Something that let other
people reading the code be alerted that "this not a regular assignement,
and it may fails".
What about "case val 1 = 2", or something alike ?

Moreover, I believe that Paul did things around that part of the
language some times ago, but I can't find them back, and so I can't
check if the question was already answered (I believe it was more likely
to be about the elimination of intermediary vals for val (a, b) = ....).

Cheers,

--
Francois ARMAND
http://fanf42.blogspot.com
http://www.normation.com

martin odersky

unread,
Aug 25, 2011, 5:19:54 AM8/25/11
to Francois, scala-debate

I am not concerned. The fact that it took 8 years for people to notice is a good sign how rare this case is. I think any proposal to "fix" this would complicate the language for no practical gain.
Just to recap the rules:

A value definition is of the form

  val <pattern> = <expression>

  1 is a <pattern>

There is one edge case: If the pattern is a single variable (upper or lower case or backquoted), then it is always treated as a variable, not a constant. Otherwise, there would be no way to define such a value.

There sure is an error here, but, as other people have said, it seems to be in the REPL, where something should be evaluated but is not.

Cheers

 -- Martin

Tony Morris

unread,
Aug 25, 2011, 5:50:09 AM8/25/11
to scala-...@googlegroups.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 25/08/11 19:19, martin odersky wrote:
> I am not concerned. The fact that it took 8 years for people to notice is a
> good sign how rare this case is

It's also a phase that all haskell newbies come to, freak out, and some
of us just kick back smoking a pipe and watch the fun begin.

let 1 = 2 in 7
7

*takes a puff*

- --
Tony Morris
http://tmorris.net/

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJOVhrRAAoJEPxHMY3rBz0PZuwH/1YdP0490MnYiRWyOQqWzBCw
ACYYK8Cugof1Vzlora9o1Vx2Mo9qmHSaKLJbryutmjfAHhmjYfFO/WT+tnogbXz9
2HjfDOwRy0n13V23J+pzDSZ2e28lDUoumDU87cFE4FhLsKfux80bVuQSa65sZOQU
PtBtWgN7qJoPtoZZHYSTVXt2gJzoFEhc9vXYED9E6ytZ8J8kBS5feiURrAodZaCD
PCDzu3AglWuy/LXmUnEgb6n08oCJowvSEgts+qidaDPdL1W2mBWtwKg0ZRzETmT7
7IW2hi0Lv2ltnBGv9t/2lgeGSIGhrOW17GKwIQvR0ShUofK6uDkK46XqPBj+M9A=
=Mro2
-----END PGP SIGNATURE-----

Francois

unread,
Aug 25, 2011, 5:54:05 AM8/25/11
to scala-...@googlegroups.com
On 25/08/2011 11:50, Tony Morris wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On 25/08/11 19:19, martin odersky wrote:
>> I am not concerned. The fact that it took 8 years for people to notice is a
>> good sign how rare this case is
> It's also a phase that all haskell newbies come to, freak out, and some
> of us just kick back smoking a pipe and watch the fun begin.
>
> let 1 = 2 in 7
> 7
>
> *takes a puff*


Well, OK, so why not just let the newbies learn that elsewhere than in
their projects, for example in some reference manual (not the spec) ? If
it is a sound behaviour, let us know about its soundness and not be
surprised.

Thanks,

√iktor Ҡlang

unread,
Aug 25, 2011, 6:14:23 AM8/25/11
to tmo...@tmorris.net, scala-...@googlegroups.com
On Thu, Aug 25, 2011 at 11:50 AM, Tony Morris <tonym...@gmail.com> wrote:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 25/08/11 19:19, martin odersky wrote:
> I am not concerned. The fact that it took 8 years for people to notice is a
> good sign how rare this case is

It's also a phase that all haskell newbies come to, freak out, and some
of us just kick back smoking a pipe and watch the fun begin.

let 1 = 2 in 7
7

*takes a puff*

Tony, that ain't no crack pipe I hope!
 

- --
Tony Morris
http://tmorris.net/

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJOVhrRAAoJEPxHMY3rBz0PZuwH/1YdP0490MnYiRWyOQqWzBCw
ACYYK8Cugof1Vzlora9o1Vx2Mo9qmHSaKLJbryutmjfAHhmjYfFO/WT+tnogbXz9
2HjfDOwRy0n13V23J+pzDSZ2e28lDUoumDU87cFE4FhLsKfux80bVuQSa65sZOQU
PtBtWgN7qJoPtoZZHYSTVXt2gJzoFEhc9vXYED9E6ytZ8J8kBS5feiURrAodZaCD
PCDzu3AglWuy/LXmUnEgb6n08oCJowvSEgts+qidaDPdL1W2mBWtwKg0ZRzETmT7
7IW2hi0Lv2ltnBGv9t/2lgeGSIGhrOW17GKwIQvR0ShUofK6uDkK46XqPBj+M9A=
=Mro2
-----END PGP SIGNATURE-----



--
Viktor Klang

Akka Tech Lead
Typesafe - Enterprise-Grade Scala from the Experts

Twitter: @viktorklang

Philippe Lhoste

unread,
Aug 25, 2011, 7:16:53 AM8/25/11
to scala-...@googlegroups.com
On 25/08/2011 11:06, Francois wrote:
> It seems to be a "feature" with a quite hight level of surprise, and a really really small
> use case surface (well, if it is still surprising among guys like Seth and Daniel today,
> well, it tells a lot).
>
> The sole thing than a "val" may leads to such exception, without warning, is quite
> deceptive. So, isn't this a perfect case for a feature removal, or at least a syntax
> change ? Something that let other people reading the code be alerted that "this not a
> regular assignement, and it may fails".
> What about "case val 1 = 2", or something alike ?

If it is a REPL-only bug, I won't worry, REPL has some other surprises, where people
report strange behavior and other people tell them they cannot reproduce it in a .scala
file. It is not a punch toward the REPL, one just has to be aware of such surprises...

Honestly, the original code, val 1 = 2, can be written only by a beginner (perhaps),
somebody doing a typo, or somebody exploring corner cases... The result is surprising, but
as long as it can be explained simply...

The use case surface isn't so small, as it is often used (and shown) with tuples.
I found out also that I can write:
val List(_, t, _*) = x
although I don't know if it is more practical than
val t = x(1)
:-)

Hey, at least, this "bug" made some people (including me) aware (or reminded) of this val
<pattern> = <expression> syntax, which is a good thing.


To "debate" on your proposal, perhaps a less breaking change would be to conform to
Daniel's expectation, that the pattern is matched only if it is surrounded between
parentheses.
Ie. val (a, b) = <expr> would work to match a tuple (ie. unchanging syntax of the most
common case), and one would have to write val (List(_, t, _*)) = <expr> to make it work.
But it looks a bit inconsistent with regard to tuples...
And given Martin's answer, I doubt this will change...

--
Philippe Lhoste
-- (near) Paris -- France
-- http://Phi.Lho.free.fr
-- -- -- -- -- -- -- -- -- -- -- -- -- --

Nate Nystrom

unread,
Aug 25, 2011, 7:33:58 AM8/25/11
to scala-...@googlegroups.com


I agree that this isn't really a big deal, but perhaps Scala could disallow val definitions where the pattern doesn't bind any variables. This rule would disallow:

val 1 = 2
val (_, _) = x

But allow:

val List(_, t, _*) = x

val (x, y) = p
val x @ 1 = 2

Is there a use case for a val declaration that doesn't bind a variable?

Nate

Daniel Sobral

unread,
Aug 25, 2011, 9:44:42 AM8/25/11
to Nate Nystrom, scala-...@googlegroups.com
On Thu, Aug 25, 2011 at 08:33, Nate Nystrom <nate.n...@gmail.com> wrote:
>
> I agree that this isn't really a big deal, but perhaps Scala could disallow val definitions where the pattern doesn't bind any variables.  This rule would disallow:
>
> val 1 = 2
> val (_, _) = x
>
> But allow:
>
> val List(_, t, _*) = x
> val (x, y) = p
> val x @ 1 = 2
>
> Is there a use case for a val declaration that doesn't bind a variable?

Perhaps a _warning_ that there's no variable being binded. But...

Interestingly, one of paulp's side branch would probably accuse an
error on "val 1 = 2", since 1.type would be different than 2.type,
causing a compilation error.

--
Daniel C. Sobral

I travel to the future all the time.

Lars Hupel

unread,
Aug 25, 2011, 11:57:22 AM8/25/11
to scala-...@googlegroups.com
> Perhaps a _warning_ that there's no variable being binded. But...

+1 for a warning

> Interestingly, one of paulp's side branch would probably accuse an
> error on "val 1 = 2", since 1.type would be different than 2.type,
> causing a compilation error.

I really like that idea. I wish there would be more singleton types
around. Which branch is that?

Razvan Cojocaru

unread,
Aug 25, 2011, 12:37:43 PM8/25/11
to tmo...@tmorris.net, scala-...@googlegroups.com
How can I retweet this ???

Thanks,
Razvan

Razvan Cojocaru

unread,
Aug 25, 2011, 1:55:03 PM8/25/11
to Nate Nystrom, scala-...@googlegroups.com
It does call the unapply(), does it?

Thanks,
Razvan

Daniel Sobral

unread,
Aug 25, 2011, 2:55:37 PM8/25/11
to Lars Hupel, scala-...@googlegroups.com

No clue. He usually says "I have a branch where x and y". I suppose
most of them are local, though you can always search at his github.

Paul Phillips

unread,
Aug 25, 2011, 4:26:42 PM8/25/11
to Daniel Sobral, Lars Hupel, scala-...@googlegroups.com
On 8/25/11 11:55 AM, Daniel Sobral wrote:
>> I really like that idea. I wish there would be more singleton types
>> around. Which branch is that?
>
> No clue. He usually says "I have a branch where x and y". I suppose
> most of them are local, though you can always search at his github.

I have been trying to move the more stable feature branches into the
repository below. This particular branch has been in there a while.

https://github.com/paulp/scala-dev/tree/literal-dependent-types

It doesn't do what you thought it might, but it was a reasonable
supposition (I had to check) and it could be made to do so; it's just a
matter of when you widen the types.

martin odersky

unread,
Aug 26, 2011, 3:30:19 AM8/26/11
to Paul Phillips, Daniel Sobral, Lars Hupel, scala-...@googlegroups.com
You certainly do want to widen the types early, or the following would no longer compile:

  var x = 1     // don't infer a 1.type for the type of x!
  x += 1

Cheers

 -- Martin

Lukas Rytz

unread,
Aug 26, 2011, 3:49:43 AM8/26/11
to Lars Hupel, scala-...@googlegroups.com
Such a warning could only be issued if both sides of the definition
are compile-time constants. I don't see why somebody would ever
write code like that.

For non-binding value definitions, they can be used as a kind of
assertion, checking the shape of a value.
  List(List(_)) = xss
I'm not arguing this is the best style :)

Kevin Wright

unread,
Aug 26, 2011, 3:54:12 AM8/26/11
to Lukas Rytz, Lars Hupel, scala-...@googlegroups.com
Ladies and Gentlemen... We have ourselves a use case!


Lars Hupel

unread,
Aug 26, 2011, 3:59:13 AM8/26/11
to scala-...@googlegroups.com
>> For non-binding value definitions, they can be used as a kind of
>> assertion, checking the shape of a value.
>> List(List(_)) = xss
>> I'm not arguing this is the best style :)
>>
> Ladies and Gentlemen... We have ourselves a use case!

May I suggest something more expressive for that?

assertMatch(xss, { case List(List(_)) => })

Lukas Rytz

unread,
Aug 26, 2011, 4:08:25 AM8/26/11
to Lars Hupel, scala-...@googlegroups.com
why writing 43 characters instead of 19? :-) 

Lars Hupel

unread,
Aug 26, 2011, 4:13:29 AM8/26/11
to scala-...@googlegroups.com
> why writing 43 characters instead of 19? :-)

You certainly have a point here. I agree that such a function (maybe on
`Predef`) incurs a significant amount of noise. But as already written
somewhere in the thread, the `val` syntax does not allow `|`. Also, a
`MatchError` is misleading for an assertion -- just because an assertion
happens to be a match does not mean we should not use an
`AssertionError` or something along those lines.

Nate Nystrom

unread,
Aug 26, 2011, 4:18:01 AM8/26/11
to Lars Hupel, scala-...@googlegroups.com


Or:

val x @ List(List(_)) = xss


Lukas Rytz

unread,
Aug 26, 2011, 4:27:18 AM8/26/11
to Lars Hupel, scala-...@googlegroups.com
I know, I was joking a bit. As said before, I'm not arguing this is the best style.

Lars Hupel

unread,
Aug 26, 2011, 4:33:57 AM8/26/11
to scala-...@googlegroups.com
> I know, I was joking a bit. As said before, I'm not arguing this is the best
> style.

Well, sorry for derailing the discussion, but I'd like to argue that
this is actually quite similar to `Predef.assert` with the minor
difference that the usual assertion methods take a `Boolean`. I see no
reason why stating that "this value should match that pattern" is not a
valid use case for assertions.

Of course, one might still say that

value match {
case pattern => doStuff
case _ => sys.error("match failed!")
}

is sufficiently concise, so I'll leave this for discussion here.

Seth Tisue

unread,
Aug 26, 2011, 11:37:06 AM8/26/11
to scala-debate, martin odersky
On Thu, Aug 25, 2011 at 5:19 AM, martin odersky <martin....@epfl.ch> wrote:
> I am not concerned. The fact that it took 8 years for people to notice is a
> good sign how rare this case is. I think any proposal to "fix" this would
> complicate the language for no practical gain.
> Just to recap the rules:
> A value definition is of the form
>   val <pattern> = <expression>
>   1 is a <pattern>
> There is one edge case: If the pattern is a single variable (upper or lower
> case or backquoted), then it is always treated as a variable, not a
> constant. Otherwise, there would be no way to define such a value.

I actually agree this is of little importance. That said:

The actual spec is more complicated than your recap indicates. I think
disallowing "val 1 = 2" would actually make the language slightly
smaller, not larger.

Value definitions are governed by SLS 4.1 and there are four different cases:
0. pattern is a simple name or a name followed by a colon and a type
1. pattern has bound variables x1, ..., xn, where n > 1
2. p has a unique bound variable x
3. p has no bound variables

Each case is spec'ed separately. #3 is the "val 1 = 2" case, and it is
already handled as an edge case with its own special expansion: "If p
has no bound variables val p = e is expanded as e match { case p =>
()}". If this case were simply prohibited, the spec would actually get
a tiny bit shorter.

If this were being spec'ed for the first time today, we might outlaw
this edge case, but since it's already spec'ed, I doubt it's worth
changing.

In any case, this has been an interesting thread.

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

Razvan Cojocaru

unread,
Aug 26, 2011, 12:07:10 PM8/26/11
to Seth Tisue, scala-debate, martin odersky
The val 1=2 doesn't bother me much, it's a sort of natural extension of the
x@ syntax... where the x@ is missing, it being optional in the first place
and it thus unifies pattern matching behavior, if not syntax and I think it
in fact simplifies the perceived language even if it has to complicate the
spec...

The upper case/lower case/backquote convention in match/case bothers me -
this is not natural... and I expect to forget it again in the future :(

Paul Phillips

unread,
Aug 26, 2011, 1:00:30 PM8/26/11
to martin odersky, Daniel Sobral, Lars Hupel, scala-...@googlegroups.com
On 8/26/11 12:30 AM, martin odersky wrote:
> You certainly do want to widen the types early, or the following would
> no longer compile:
>
> var x = 1 // don't infer a 1.type for the type of x!
> x += 1

Yes, but that doesn't preclude having 1 match { case 2 => } statically
fail. You have to widen the types of values which are mutable or which
can be overridden (at least if you want to be useful) but neither is
true of literals.

Jim Powers

unread,
Sep 1, 2011, 9:32:32 AM9/1/11
to scala-...@googlegroups.com
On Thu, Aug 25, 2011 at 5:50 AM, Tony Morris <tonym...@gmail.com> wrote:
It's also a phase that all haskell newbies come to, freak out, and some
of us just kick back smoking a pipe and watch the fun begin.

let 1 = 2 in 7
7

Wouldn't the more surprising (and puff-worthy) case be:

let 1 = 2 in 1
1

;-)

-- 
Jim Powers

Jim Powers

unread,
Sep 1, 2011, 11:47:20 AM9/1/11
to Lukas Rytz, Lars Hupel, scala-...@googlegroups.com
On Fri, Aug 26, 2011 at 3:49 AM, Lukas Rytz <lukas...@epfl.ch> wrote:
For non-binding value definitions, they can be used as a kind of
assertion, checking the shape of a value.
  List(List(_)) = xss
I'm not arguing this is the best style :)

Shouldn't the shape of something already be captured in its type?

--
Jim Powers

Seth Tisue

unread,
Sep 6, 2011, 5:36:50 PM9/6/11
to scala-...@googlegroups.com

This "assertion" checks not only the type (List[List[T]]), but also
that the outer and the inner list each contain exactly one element.

Or maybe you realize that and you're making a more philosophical
point. I can't tell. If so, feel free to expand on it :-)

Jim Powers

unread,
Sep 6, 2011, 5:53:03 PM9/6/11
to Seth Tisue, scala-...@googlegroups.com
On Tue, Sep 6, 2011 at 5:36 PM, Seth Tisue <se...@tisue.net> wrote:
On Thu, Sep 1, 2011 at 11:47 AM, Jim Powers <j...@casapowers.com> wrote:
> On Fri, Aug 26, 2011 at 3:49 AM, Lukas Rytz <lukas...@epfl.ch> wrote:
>>
>> For non-binding value definitions, they can be used as a kind of
>> assertion, checking the shape of a value.
>>   List(List(_)) = xss
>> I'm not arguing this is the best style :)
>
> Shouldn't the shape of something already be captured in its type?

This "assertion" checks not only the type (List[List[T]]), but also
that the outer and the inner list each contain exactly one element.

Or maybe you realize that and you're making a more philosophical
point. I can't tell. If so, feel free to expand on it :-)

I would guess that the more philosophical point would be closer to the target.  It doesn't seem like a good way to test the condition of a list containing a list of one element.  The input type allows for a large space of nested lists and the code surrounding the example line ought to be correctly dealing with the variations in a clear manner (as Lukas points out: clearly this is not a "best style" ;-) ).  If such an example existed in an actual body of "production" code it would appear that the author would need education in the use of Option (more specifically Option[Option[T]]) as opposed to relying on the exception mechanism to direct program flow :-).

-- 
Jim Powers

Reply all
Reply to author
Forward
0 new messages