Scala:你能在没有括号的表达式中使用“foo match {bar}”吗?

时间:2011-09-23 13:26:33

标签: scala match operator-precedence

为什么这里需要括号?我应该知道一些优先规则吗?

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

谢谢!

3 个答案:

答案 0 :(得分:8)

正如Agilesteel所说,匹配不被视为简单表达式,也不是if语句,因此您需要用括号括起表达式。从The Scala Language Specification,6个表达式,p73开始,匹配是Expr,if是if。 +运算符的任何一侧都只接受SimpleExpr。

要将Expr转换为SimpleExpr,您必须用()包围它。

复制完整性:

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}
    | ‘:’ ‘_’ ‘*’

答案 1 :(得分:5)

在Scala规范中进行一些检查后,我想我可以试一试。 如果我错了,请纠正我。

首先,ifmatch定义为Expr - 表达式。

您正在尝试创建中缀表达式(通过在两个表达式之间使用运算符来定义)

然而,especification(第3.2.8节)指出:

  

fi x运算符中的所有类型都具有相同的优先级;括号必须   用于分组

它还声明:

  

在fi x运算中连续类型的序列t0 op1 t1 op2。 。   .opn tn,所有操作符op1 ,. 。 。 ,opn必须具有相同的功能   关联。如果它们都是左关联的,那么序列就是   解释为(...(t0 op1 t1)op2 ...)opn tn。

所以我的看法是Scala不知道首先要减少什么:匹配或方法'+'调用。

看看这个answer

如果我错了,请纠正我。

答案 2 :(得分:3)

匹配表达式不被视为简单表达式。这是一个类似的例子:

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

显然你无法在任何地方编写复杂的表达式。我不知道为什么,希望对这个主题有更多了解的人会给你一个更好的答案。