- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Misleading error message for " e1 op e2 " where e2 is a repeated parameter
Fri, 2009-02-13, 14:41
Hello,
I was just getting in the habit of leaving out dots and parentheses when I ran into this problem.
scala> val q = new scala.collection.mutable.Queue[Int]()
q: scala.collection.mutable.Queue[Int] = Queue()
scala> val s:Seq[Int] = Array.range(0, 4)
s: Seq[Int] = Array(0, 1, 2, 3)
scala> q enqueue(1) // OK
scala> q enqueue 1 // OK
scala> q enqueue(s:_*) // OK
scala> q enqueue s:_* // NOK
<console>:7: error: type mismatch;
found : Seq[Int]
required: Int
q enqueue s:_*
^
It took me a little while when I first encountered this error to figure out that this was just because of missing parentheses. May I suggest to replace the "type mismatch" error with something more explicit like "annotation ': _ *' not allowed outside parentheses".
For example, something similar is displayed when you type:
scala> s:_*
<console>:9: error: no `: _*' annotation allowed here
(such annotations are only allowed in arguments to *-parameters)
s:_*
Now the Scala spec p.79 says "A left-associative binary operation e1 op e2 is interpreted as e1.op(e2)."
Obviously there are exceptions to the rule. I know the operator notation was not initially designed to save time for lazy typists but I'm wondering if there is any good reason why it couldn't work in the context of a binary operation?
Thank you,
Sebastien
I was just getting in the habit of leaving out dots and parentheses when I ran into this problem.
scala> val q = new scala.collection.mutable.Queue[Int]()
q: scala.collection.mutable.Queue[Int] = Queue()
scala> val s:Seq[Int] = Array.range(0, 4)
s: Seq[Int] = Array(0, 1, 2, 3)
scala> q enqueue(1) // OK
scala> q enqueue 1 // OK
scala> q enqueue(s:_*) // OK
scala> q enqueue s:_* // NOK
<console>:7: error: type mismatch;
found : Seq[Int]
required: Int
q enqueue s:_*
^
It took me a little while when I first encountered this error to figure out that this was just because of missing parentheses. May I suggest to replace the "type mismatch" error with something more explicit like "annotation ': _ *' not allowed outside parentheses".
For example, something similar is displayed when you type:
scala> s:_*
<console>:9: error: no `: _*' annotation allowed here
(such annotations are only allowed in arguments to *-parameters)
s:_*
Now the Scala spec p.79 says "A left-associative binary operation e1 op e2 is interpreted as e1.op(e2)."
Obviously there are exceptions to the rule. I know the operator notation was not initially designed to save time for lazy typists but I'm wondering if there is any good reason why it couldn't work in the context of a binary operation?
Thank you,
Sebastien
Fri, 2009-02-13, 15:47
#2
Re: Misleading error message for " e1 op e2 " where e2 is a re
There is still something I don't understand. If the spec says "e1 op e2 is interpreted as e1.op(e2)", why is the expresion "s:_*" evaluated to a sequence in one context and to a variable argument list in the other context?
Doesn't "interpreted" means "parses like"?
2009/2/13 Ricky Clarkson <ricky.clarkson@gmail.com>
Doesn't "interpreted" means "parses like"?
2009/2/13 Ricky Clarkson <ricky.clarkson@gmail.com>
How x y z:T parses should not depend on what x, y and z are. That
would massively complicate parsing.
2009/2/13 Sébastien Bocq <sebastien.bocq@gmail.com>:
- Afficher le texte des messages précédents -> Hello,
>
> I was just getting in the habit of leaving out dots and parentheses when I
> ran into this problem.
>
> scala> val q = new scala.collection.mutable.Queue[Int]()
> q: scala.collection.mutable.Queue[Int] = Queue()
>
> scala> val s:Seq[Int] = Array.range(0, 4)
> s: Seq[Int] = Array(0, 1, 2, 3)
>
> scala> q enqueue(1) // OK
>
> scala> q enqueue 1 // OK
>
> scala> q enqueue(s:_*) // OK
>
> scala> q enqueue s:_* // NOK
>
> <console>:7: error: type mismatch;
> found : Seq[Int]
> required: Int
> q enqueue s:_*
> ^
> It took me a little while when I first encountered this error to figure out
> that this was just because of missing parentheses. May I suggest to replace
> the "type mismatch" error with something more explicit like "annotation ': _
> *' not allowed outside parentheses".
>
> For example, something similar is displayed when you type:
>
> scala> s:_*
> <console>:9: error: no `: _*' annotation allowed here
> (such annotations are only allowed in arguments to *-parameters)
> s:_*
>
> Now the Scala spec p.79 says "A left-associative binary operation e1 op e2
> is interpreted as e1.op(e2)."
>
> Obviously there are exceptions to the rule. I know the operator notation was
> not initially designed to save time for lazy typists but I'm wondering if
> there is any good reason why it couldn't work in the context of a binary
> operation?
>
> Thank you,
> Sebastien
>
Fri, 2009-02-13, 15:57
#3
Re: Misleading error message for " e1 op e2 " where e2 is a rep
On Fri, Feb 13, 2009 at 03:35:15PM +0100, Sébastien Bocq wrote:
> There is still something I don't understand. If the spec says "e1 op e2 is
> interpreted as e1.op(e2)", why is the expresion "s:_*" evaluated to a
> sequence in one context and to a variable argument list in the other
> context?
What did you think the parentheses were accomplishing?
Fri, 2009-02-13, 16:27
#4
Re: Misleading error message for " e1 op e2 " where e2 is a re
Well, I thought the parser would insert automatically the parentheses when building the parse tree. Anyway, it's been a while since my last course on compiler theory and I probably need to learn more about abstract syntax tree as well.
Thank you all for your answers.
Sebastien
2009/2/13 Paul Phillips <paulp@improving.org>
Thank you all for your answers.
Sebastien
2009/2/13 Paul Phillips <paulp@improving.org>
On Fri, Feb 13, 2009 at 03:35:15PM +0100, Sébastien Bocq wrote:
> There is still something I don't understand. If the spec says "e1 op e2 is
> interpreted as e1.op(e2)", why is the expresion "s:_*" evaluated to a
> sequence in one context and to a variable argument list in the other
> context?
What did you think the parentheses were accomplishing?
--
Paul Phillips | We must respect the other fellow's religion, but only
Future Perfect | in the sense and to the extent that we respect his
Empiricist | theory that his wife is beautiful and his children smart.
pal, i pill push | -- H. L. Mencken
Sat, 2009-02-14, 11:47
#5
Re: Misleading error message for " e1 op e2 " where e2 is a re
You can think of it in 3 stages:
1. Lexing splits the text up so that foo(bar) is
List(Identifier("foo"), LeftParen, Identifier("bar"), RightParen).
2. Parsing handles precedence etc., and turns the lexer's output into
a tree - List(Call(Identifier("foo"), Args(Identifier("bar"))).
3. The rest of the compiler takes the parser's output and does all
remaining things, inferring types etc.
So to require stage 2 to adjust the precedence based on the types of
the identifiers, in other words, a "do what I mean" parser, would make
the interaction between stage 2 and stage 3 much more complicated, and
for many language grammars, it would make the compiler potentially
non-terminating.
Sadly, my CS degree had no CS in it, so I've never had a course on compilers.
2009/2/13 Sébastien Bocq :
> Well, I thought the parser would insert automatically the parentheses when
> building the parse tree. Anyway, it's been a while since my last course on
> compiler theory and I probably need to learn more about abstract syntax tree
> as well.
>
> Thank you all for your answers.
> Sebastien
>
> 2009/2/13 Paul Phillips
>>
>> On Fri, Feb 13, 2009 at 03:35:15PM +0100, Sébastien Bocq wrote:
>> > There is still something I don't understand. If the spec says "e1 op e2
>> > is
>> > interpreted as e1.op(e2)", why is the expresion "s:_*" evaluated to a
>> > sequence in one context and to a variable argument list in the other
>> > context?
>>
>> What did you think the parentheses were accomplishing?
>>
>> --
>> Paul Phillips | We must respect the other fellow's religion, but only
>> Future Perfect | in the sense and to the extent that we respect his
>> Empiricist | theory that his wife is beautiful and his children
>> smart.
>> pal, i pill push | -- H. L. Mencken
>
>
Sat, 2009-02-14, 14:47
#6
Re: Misleading error message for " e1 op e2 " where e2 is a re
On Sat, Feb 14, 2009 at 11:40 AM, Ricky Clarkson <ricky.clarkson@gmail.com> wrote:
You can think of it in 3 stages:
1. Lexing splits the text up so that foo(bar) is
List(Identifier("foo"), LeftParen, Identifier("bar"), RightParen).
2. Parsing handles precedence etc., and turns the lexer's output into
a tree - List(Call(Identifier("foo"), Args(Identifier("bar"))).
3. The rest of the compiler takes the parser's output and does all
remaining things, inferring types etc.
So to require stage 2 to adjust the precedence based on the types of
the identifiers, in other words, a "do what I mean" parser, would make
the interaction between stage 2 and stage 3 much more complicated, and
for many language grammars, it would make the compiler potentially
non-terminating.
Sadly, my CS degree had no CS in it, so I've never had a course on compilers.
They have degrees in CounterStrike now?
2009/2/13 Sébastien Bocq <sebastien.bocq@gmail.com>:
> Well, I thought the parser would insert automatically the parentheses when
> building the parse tree. Anyway, it's been a while since my last course on
> compiler theory and I probably need to learn more about abstract syntax tree
> as well.
>
> Thank you all for your answers.
> Sebastien
>
> 2009/2/13 Paul Phillips <paulp@improving.org>
>>
>> On Fri, Feb 13, 2009 at 03:35:15PM +0100, Sébastien Bocq wrote:
>> > There is still something I don't understand. If the spec says "e1 op e2
>> > is
>> > interpreted as e1.op(e2)", why is the expresion "s:_*" evaluated to a
>> > sequence in one context and to a variable argument list in the other
>> > context?
>>
>> What did you think the parentheses were accomplishing?
>>
>> --
>> Paul Phillips | We must respect the other fellow's religion, but only
>> Future Perfect | in the sense and to the extent that we respect his
>> Empiricist | theory that his wife is beautiful and his children
>> smart.
>> pal, i pill push | -- H. L. Mencken
>
>
--
Viktor Klang
Senior Systems Analyst
Sun, 2009-02-15, 11:57
#7
Re: Misleading error message for " e1 op e2 " where e2 is a re
Well ... to tell you the truth, I'm still suspecting there is some magic in the parser with "e1 op e2" :)
See for example:
scala> q enqueue (1,2,3):Int
<console>:9: error: type mismatch;
found : Unit
required: Int
q enqueue (1,2,3):Int
^
scala> (1,2,3):Int
<console>:7: error: type mismatch;
found : (Int, Int, Int)
required: Int
(1,2,3):Int
^
If in both cases there are no parentheses and parsing should not depend on what x y z are, why are there two different errors? And where does Unit comes from in the first case? I would be very thankful if somebody could explain me that.
Titles are just titles, in the end it is your experience and what you do with it that matter. That is especially true in Counter Strike :)
2009/2/14 Ricky Clarkson <ricky.clarkson@gmail.com>
See for example:
scala> q enqueue (1,2,3):Int
<console>:9: error: type mismatch;
found : Unit
required: Int
q enqueue (1,2,3):Int
^
scala> (1,2,3):Int
<console>:7: error: type mismatch;
found : (Int, Int, Int)
required: Int
(1,2,3):Int
^
If in both cases there are no parentheses and parsing should not depend on what x y z are, why are there two different errors? And where does Unit comes from in the first case? I would be very thankful if somebody could explain me that.
Titles are just titles, in the end it is your experience and what you do with it that matter. That is especially true in Counter Strike :)
2009/2/14 Ricky Clarkson <ricky.clarkson@gmail.com>
You can think of it in 3 stages:
1. Lexing splits the text up so that foo(bar) is
List(Identifier("foo"), LeftParen, Identifier("bar"), RightParen).
2. Parsing handles precedence etc., and turns the lexer's output into
a tree - List(Call(Identifier("foo"), Args(Identifier("bar"))).
3. The rest of the compiler takes the parser's output and does all
remaining things, inferring types etc.
So to require stage 2 to adjust the precedence based on the types of
the identifiers, in other words, a "do what I mean" parser, would make
the interaction between stage 2 and stage 3 much more complicated, and
for many language grammars, it would make the compiler potentially
non-terminating.
Sadly, my CS degree had no CS in it, so I've never had a course on compilers.
2009/2/13 Sébastien Bocq <sebastien.bocq@gmail.com>:
> Well, I thought the parser would insert automatically the parentheses when
> building the parse tree. Anyway, it's been a while since my last course on
> compiler theory and I probably need to learn more about abstract syntax tree
> as well.
>
> Thank you all for your answers.
> Sebastien
>
> 2009/2/13 Paul Phillips <paulp@improving.org>
>>
>> On Fri, Feb 13, 2009 at 03:35:15PM +0100, Sébastien Bocq wrote:
>> > There is still something I don't understand. If the spec says "e1 op e2
>> > is
>> > interpreted as e1.op(e2)", why is the expresion "s:_*" evaluated to a
>> > sequence in one context and to a variable argument list in the other
>> > context?
>>
>> What did you think the parentheses were accomplishing?
>>
Sun, 2009-02-15, 15:17
#8
Re: Misleading error message for " e1 op e2 " where e2 is a rep
On Sun, Feb 15, 2009 at 11:52:13AM +0100, Sébastien Bocq wrote:
> scala> q enqueue (1,2,3):Int
> :9: error: type mismatch;
> found : Unit
> required: Int
> q enqueue (1,2,3):Int
> ^
>
> scala> (1,2,3):Int
> :7: error: type mismatch;
> found : (Int, Int, Int)
> required: Int
> (1,2,3):Int
> ^
>
> If in both cases there are no parentheses and parsing should not depend on
> what x y z are, why are there two different errors?
Because in the first one (1,2,3) is an argument list and in the second one it's a tuple. The Unit is the
return type of the call to enqueue. Scala has its share of surprising corners but these really aren't them.
Sun, 2009-02-15, 17:27
#9
Re: Misleading error message for " e1 op e2 " where e2 is a re
The spec says (p.79) "operators starting with a letter have lowest precedence", why is not the case with:
scala> q enqueue 1:Int
<console>:9: error: type mismatch;
found : Unit
required: Int
q enqueue 1:Int
^
In contrast to the examples:
scala> 3 | 4:String
<console>:7: error: type mismatch;
found : Int(7) // '|' has higher precedence than ':'
required: String
3 | 4:String
^
scala> 3 + 4:String
<console>:7: error: type mismatch;
found : Int(4) // ':' has higher precedence than '+'
required: java.lang.String
3 + 4:String
^
Many thanks for your patience!
Sebastien
2009/2/15 Paul Phillips <paulp@improving.org>
scala> q enqueue 1:Int
<console>:9: error: type mismatch;
found : Unit
required: Int
q enqueue 1:Int
^
In contrast to the examples:
scala> 3 | 4:String
<console>:7: error: type mismatch;
found : Int(7) // '|' has higher precedence than ':'
required: String
3 | 4:String
^
scala> 3 + 4:String
<console>:7: error: type mismatch;
found : Int(4) // ':' has higher precedence than '+'
required: java.lang.String
3 + 4:String
^
Many thanks for your patience!
Sebastien
2009/2/15 Paul Phillips <paulp@improving.org>
On Sun, Feb 15, 2009 at 11:52:13AM +0100, Sébastien Bocq wrote:
> scala> q enqueue (1,2,3):Int
> <console>:9: error: type mismatch;
> found : Unit
> required: Int
> q enqueue (1,2,3):Int
> ^
>
> scala> (1,2,3):Int
> <console>:7: error: type mismatch;
> found : (Int, Int, Int)
> required: Int
> (1,2,3):Int
> ^
>
> If in both cases there are no parentheses and parsing should not depend on
> what x y z are, why are there two different errors?
Because in the first one (1,2,3) is an argument list and in the second one it's a tuple. The Unit is the
return type of the call to enqueue. Scala has its share of surprising corners but these really aren't them.
--
Paul Phillips | The most dangerous man to any government is the man who
Caged Spirit | is able to think things out [...] Almost inevitably he
Empiricist | comes to the conclusion that the government he lives under
pp: i haul pills | is dishonest, insane, intolerable. -- H. L. Mencken
Sun, 2009-02-15, 17:57
#10
Re: Misleading error message for " e1 op e2 " where e2 is a rep
On Sun, Feb 15, 2009 at 05:22:03PM +0100, Sébastien Bocq wrote:
> The spec says (p.79) "operators starting with a letter have lowest
> precedence", why is not the case with:
: isn't an operator, it's a reserved word. Note the difference:
scala> def :(x: Int) = x
:1: error: identifier expected but ':' found.
def :(x: Int) = x
^
scala> def |(x: Int) = x
$bar: (Int)Int
Sun, 2009-02-15, 18:37
#11
Re: Misleading error message for " e1 op e2 " where e2 is a re
Ok, yet ':' follows the operator precedence rules during evaluation.
"3 | 4:String" is evaluated as "(3 | 4):String"
"3 + 4:String" is evaluated as "3 + (4:String)"
So why is:
"q enqueue 1:Int" evaluated as "(q enqueue 1):Int" instead of "q enqueue (1:Int)"
and why does the parentheses are ignored when I type:
scala> (3 + 4):String
<console>:7: error: type mismatch;
found : Int(4)
required: java.lang.String
(3 + 4):String
^
I'm still learning Scala and I've never seen this in other languages before. Could you point me to a paper/tutorial explaining how the evaluation works in Scala?
2009/2/15 Paul Phillips <paulp@improving.org>
"3 | 4:String" is evaluated as "(3 | 4):String"
"3 + 4:String" is evaluated as "3 + (4:String)"
So why is:
"q enqueue 1:Int" evaluated as "(q enqueue 1):Int" instead of "q enqueue (1:Int)"
and why does the parentheses are ignored when I type:
scala> (3 + 4):String
<console>:7: error: type mismatch;
found : Int(4)
required: java.lang.String
(3 + 4):String
^
I'm still learning Scala and I've never seen this in other languages before. Could you point me to a paper/tutorial explaining how the evaluation works in Scala?
2009/2/15 Paul Phillips <paulp@improving.org>
On Sun, Feb 15, 2009 at 05:22:03PM +0100, Sébastien Bocq wrote:
> The spec says (p.79) "operators starting with a letter have lowest
> precedence", why is not the case with:
: isn't an operator, it's a reserved word. Note the difference:
scala> def :(x: Int) = x
<console>:1: error: identifier expected but ':' found.
def :(x: Int) = x
^
scala> def |(x: Int) = x
$bar: (Int)Int
--
Paul Phillips | Adultery is the application of democracy to love.
Moral Alien | -- H. L. Mencken
Empiricist |
i'll ship a pulp |----------* http://www.improving.org/paulp/ *----------
Sun, 2009-02-15, 19:07
#12
Re: Misleading error message for " e1 op e2 " where e2 is a rep
On Sun, Feb 15, 2009 at 06:35:00PM +0100, Sébastien Bocq wrote:
> Ok, yet ':' follows the operator precedence rules during evaluation.
Well, maybe. I don't have time to pick apart the scanner on your behalf, but I can tell you that colon is
treated specially, not generically, so it's perfectly capable of behaving differently from everything else.
There are productions like this:
/* TypedOpt ::= [`:' Type]
And this
* ResultExpr ::= (Bindings | Id `:' CompoundType) `=>' Block
* | Expr1
> and why does the parentheses are ignored when I type:
>
> scala> (3 + 4):String
> :7: error: type mismatch;
> found : Int(4)
> required: java.lang.String
> (3 + 4):String
> ^
This is because of the implicit conversion any2stringadd. The parens aren't ignored, it's just not reporting
the error you expect because after it fails to typecheck it tries to apply the implicit. Try this:
scala> class Foo
defined class Foo
scala> (3 + 4):Foo
:6: error: type mismatch;
found : Int(7)
required: Foo
(3 + 4):Foo
^
> I'm still learning Scala and I've never seen this in other languages before. Could you point me to a
> paper/tutorial explaining how the evaluation works in Scala?
I can only point you at the source of my meager knowledge:
Sun, 2009-02-15, 19:17
#13
Re: Misleading error message for " e1 op e2 " where e2 is a re
> I'm still learning Scala and I've never seen this in other languages before. Could you point me to a
> paper/tutorial explaining how the evaluation works in Scala?
I can only point you at the source of my meager knowledge:
http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk/
Ok, I thought about something a bit more "entry level", maybe I'll have a look someday :)
Thanks,
Sebastien
How x y z:T parses should not depend on what x, y and z are. That
would massively complicate parsing.
2009/2/13 Sébastien Bocq :
> Hello,
>
> I was just getting in the habit of leaving out dots and parentheses when I
> ran into this problem.
>
> scala> val q = new scala.collection.mutable.Queue[Int]()
> q: scala.collection.mutable.Queue[Int] = Queue()
>
> scala> val s:Seq[Int] = Array.range(0, 4)
> s: Seq[Int] = Array(0, 1, 2, 3)
>
> scala> q enqueue(1) // OK
>
> scala> q enqueue 1 // OK
>
> scala> q enqueue(s:_*) // OK
>
> scala> q enqueue s:_* // NOK
>
> :7: error: type mismatch;
> found : Seq[Int]
> required: Int
> q enqueue s:_*
> ^
> It took me a little while when I first encountered this error to figure out
> that this was just because of missing parentheses. May I suggest to replace
> the "type mismatch" error with something more explicit like "annotation ': _
> *' not allowed outside parentheses".
>
> For example, something similar is displayed when you type:
>
> scala> s:_*
> :9: error: no `: _*' annotation allowed here
> (such annotations are only allowed in arguments to *-parameters)
> s:_*
>
> Now the Scala spec p.79 says "A left-associative binary operation e1 op e2
> is interpreted as e1.op(e2)."
>
> Obviously there are exceptions to the rule. I know the operator notation was
> not initially designed to save time for lazy typists but I'm wondering if
> there is any good reason why it couldn't work in the context of a binary
> operation?
>
> Thank you,
> Sebastien
>