9

Why are the parentheses needed here? Are there some precedence rules I should know?

scala> 'x' match { case _ => 1 } + 1
<console>:1: error: ';' expected but identifier found.
       'x' match { case _ => 1 } + 1
                                 ^

scala> ('x' match { case _ => 1 }) + 1
res2: Int = 2

Thanks!

3 Answers3

8

As Agilesteel says, a match is not considered as a simple expression, nor is an if statement, so you need to surround the expression with parentheses. From The Scala Language Specification, 6 Expressions, p73, the match is an Expr, as is an if. Only SimpleExpr are accepted either side of the + operator.

To convert an Expr into a SimpleExpr, you have to surround it with ().

Copied for completeness:

Expr ::= (Bindings | id | ‘_’) ‘=>’ Expr
    | Expr1
Expr1 ::= ‘if’ ‘(’ Expr ‘)’ {nl} Expr [[semi] else Expr]
    | ‘while’ ‘(’ Expr ‘)’ {nl} Expr
    | ‘try’ ‘{’ Block ‘}’ [‘catch’ ‘{’ CaseClauses ‘}’] [‘finally’ Expr]
    | ‘do’ Expr [semi] ‘while’ ‘(’ Expr ’)’
    | ‘for’ (‘(’ Enumerators ‘)’ | ‘{’ Enumerators ‘}’) {nl} [‘yield’] Expr
    | ‘throw’ Expr
    | ‘return’ [Expr]
    | [SimpleExpr ‘.’] id ‘=’ Expr
    | SimpleExpr1 ArgumentExprs ‘=’ Expr
    | PostfixExpr
    | PostfixExpr Ascription
    | PostfixExpr ‘match’ ‘{’ CaseClauses ‘}’
PostfixExpr ::= InfixExpr [id [nl]]
InfixExpr ::= PrefixExpr
    | InfixExpr id [nl] InfixExpr
PrefixExpr ::= [‘-’ | ‘+’ | ‘~’ | ‘!’] SimpleExpr
SimpleExpr ::= ‘new’ (ClassTemplate | TemplateBody)
    | BlockExpr
    | SimpleExpr1 [‘_’]
SimpleExpr1 ::= Literal
    | Path
    | ‘_’
    | ‘(’ [Exprs] ‘)’
    | SimpleExpr ‘.’ id s
    | SimpleExpr TypeArgs
    | SimpleExpr1 ArgumentExprs
    | XmlExpr
Exprs ::= Expr {‘,’ Expr}
BlockExpr ::= ‘{’ CaseClauses ‘}’
    | ‘{’ Block ‘}’
Block ::= {BlockStat semi} [ResultExpr]
ResultExpr ::= Expr1
    | (Bindings | ([‘implicit’] id | ‘_’) ‘:’ CompoundType) ‘=>’ Block
Ascription ::= ‘:’ InfixType
    | ‘:’ Annotation {Annotation}
    | ‘:’ ‘_’ ‘*’
Matthew Farwell
  • 60,889
  • 18
  • 128
  • 171
5

After some inspection in the Scala specification, I think I can give it a shot. If I am wrong please correct me.

first, an if or match are defined as Expr - expressions.

You are trying to create an infix expression (defined by the use of the operator between two expressions)

However the especification (section 3.2.8) states that :

All type infix operators have the same precedence; parentheses have to be used for grouping

It also also states that:

In a sequence of consecutive type infix operations t0 op1 t1 op2 . . .opn tn, all operators op1, . . . , opn must have the same associativity. If they are all left-associative, the sequence is interpreted as (. . . (t0 op1 t1) op2 . . .) opn tn.

So my take is that Scala does not know what to reduce first: the match or the method '+' invocation.

Take a look at this answer

Please correct me if I am wrong.

Community
  • 1
  • 1
JaimeJorge
  • 1,885
  • 16
  • 15
  • 1
    Thanks! This seems like an oversight in the syntax to me. And the part of the spec on `‘(’ [Exprs] ‘)’` (section 6.9: Tuple) does not talk about the case where there is only one expression between the parentheses, is it defined elsewhere? – Guillaume Martres Sep 23 '11 at 15:02
  • Welcome. In the Scala Syntax Summary (page 162) of http://www.scala-lang.org/docu/files/ScalaReference.pdf Exprs is defined as Expr {',' Expr} which is represents repetition of the expression (http://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_Form). So that can represent one expression or repeated expressions. – JaimeJorge Sep 23 '11 at 15:17
  • Thanks but I meant that 6.9 only says `A tuple expression (e 1 , . . . , e n ) is an alias for the class instance creation scala.Tuplen (e 1 , . . . , e n ), where n ≥ 2. The empty tuple () is the unique value of type scala.Unit.`. The n = 1 case is not mentioned. – Guillaume Martres Sep 23 '11 at 15:42
  • Indeed. It does not seem to make sense. I must be wrong in the grammar matching, since Exprs match function arguments, tuples, etc. I am on this. :) – JaimeJorge Sep 23 '11 at 15:45
  • Feel free to revise, since I want to be sure this is correct :) – JaimeJorge Sep 23 '11 at 16:40
  • Apparently there's a Tuple1 class, but `Tuple1(1) + 1` gives an error so I guess that's not what is called. From looking at scala/tools/nsc/ast/parser/Parsers.java it might just be because of what you and Matthew Farwell said, the parser looks for a SimpleExpr and gets confused. – Guillaume Martres Sep 23 '11 at 18:35
3

A match expression is not considered as simple expression. Here is a similar example:

scala> val foo = "bar" + if(3 < 5) 3 else 5   // does not compile
scala> val foo = "bar" + (if(3 < 5) 3 else 5) // does compile

Apparently you can't write complex expressions wherever you want. I don't know why and hope that someone with more knowledge of the topic will give you a better answer.

agilesteel
  • 16,775
  • 6
  • 44
  • 55