当您省略点和括号时,您使用所谓的中缀表示法。它允许您编写a + b
而不是a.+(b)
. 这里的一个重要规则是,仅当调用具有以下形式时才允许这样做object method paramlist
(请参阅SLS 6.12.3):
左结合运算符的右手操作数可能由括号括起来的几个参数组成,例如e op (e 1 , ... , e n )
. 然后将该表达式解释为e.op(e 1 , ... , e n )
。
foldLeft
不适合这种形式,它使用object method paramlist1 paramlist2
. 因此,如果您用运算符表示法编写此代码,编译器会将其视为object.method(paramlist1).paramlist2
(如SLS 6.12.2中所述):
后缀运算符可以是任意标识符。后缀操作e op
被解释为e.op
.
但这里应用了另一条规则:函数应用程序(SLS 6.6)。
应用程序f(e 1 , ... , e m)
将该函数应用于f
参数表达式
e 1 , ... , e m
。
[...]
如果f
具有某种值类型,则应用程序被视为等效于f.apply(e 1 , ... , e m)
,即由 定义的应用方法的应用程序f
。
开始了:
scala> { (a, x) => a + x }
<console>:12: error: missing parameter type
{ (a, x) => a + x }
^
<console>:12: error: missing parameter type
{ (a, x) => a + x }
^
这只是一个缺少类型参数的函数文字。如果我们添加它们,一切都编译得很好:
scala> { (a: String, x: Wrapper[String]) => a + x }
res6: (String, Wrapper[String]) => String = <function2>
编译器只是应用上述关于函数应用的规则:
scala> "" { (a: String, x: Wrapper[String]) => a + x }
<console>:13: error: type mismatch;
found : (String, Wrapper[String]) => String
required: Int
"" { (a: String, x: Wrapper[String]) => a + x }
^
scala> "" apply { (a: String, x: Wrapper[String]) => a + x }
<console>:13: error: type mismatch;
found : (String, Wrapper[String]) => String
required: Int
"" apply { (a: String, x: Wrapper[String]) => a + x }
^
因此,您的代码被解释为
scala> xs foldLeft ("").apply{ (a: String, x: Wrapper[String]) => a + x }
<console>:14: error: type mismatch;
found : (String, Wrapper[String]) => String
required: Int
xs foldLeft ("").apply{ (a: String, x: Wrapper[String]) => a + x }
^
但是为什么它会应用函数应用程序规则呢?也可以将函数文字用作后缀运算符。要找出我们收到显示的错误消息的原因,我们需要查看SLS Scala Syntax Summary。在那里我们可以看到以下内容:
InfixExpr ::= PrefixExpr
| InfixExpr id [nl] InfixExpr
PrefixExpr ::= [‘-’ | ‘+’ | ‘~’ | ‘!’] SimpleExpr
SimpleExpr ::= ‘new’ (ClassTemplate | TemplateBody)
| BlockExpr
| SimpleExpr1 [‘_’]
SimpleExpr1 ::= Literal
| Path
| ‘_’
| ‘(’ [Exprs] ‘)’
| SimpleExpr ‘.’ id
| SimpleExpr TypeArgs
| SimpleExpr1 ArgumentExprs
| XmlExpr
Exprs ::= Expr {‘,’ Expr}
ArgumentExprs ::= ‘(’ [Exprs] ‘)’
| ‘(’ [Exprs ‘,’] PostfixExpr ‘:’ ‘_’ ‘*’ ‘)’
| [nl] BlockExpr
从上面描述的部分我们知道ArgumentExprs
描述函数应用程序同时InfixExpr
描述中缀表达式。由于EBNF的规则,最高的规则具有最低的优先级。并且因为前一个规则被后一个规则调用,这意味着函数字面量是在中缀表达式之前应用的,因此会出现错误消息。