When you leave out the dot and the parentheses you use the so called infix notation. It allows you to write a + b
instead of a.+(b)
. An important rule here is that this is only allowed if a call is of the form object method paramlist
(see SLS 6.12.3):
The right-hand operand of a left-associative operator may consist of several arguments enclosed in parentheses, e.g. e op (e 1 , ... , e n )
. This expression is then interpreted as e.op(e 1 , ... , e n )
.
foldLeft
doesn't fit into this form, it uses object method paramlist1 paramlist2
. Thus if you write this in operator notation the compiler treats it as object.method(paramlist1).paramlist2
(as described in SLS 6.12.2):
A postfix operator can be an arbitrary identifier. The postfix operation e op
is interpreted as e.op
.
But there is another rule applied here: Function Applications (SLS 6.6).
An application f(e 1 , ... , e m)
applies the function f
to the argument expressions
e 1 , ... , e m
.
[...]
If f
has some value type, the application is taken to be equivalent to f.apply(e 1 , ... , e m)
, i.e. the application of an apply method defined by f
.
Here we go:
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 }
^
This is just a function literals that misses its type arguments. If we add them everything compiles fine:
scala> { (a: String, x: Wrapper[String]) => a + x }
res6: (String, Wrapper[String]) => String = <function2>
The compiler just applies the rule about function applications described above:
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 }
^
Thus, your code is interpreted as
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 }
^
But why does it apply the functions applications rule? It would also be possible to apply the function literal as postfix operator. To find out why we get the shown error message wen need to look at SLS Scala Syntax Summary. There we can see the following:
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
From the sections described above we know that ArgumentExprs
describes function application while InfixExpr
describes an infix expression. Because of the rules of EBNF, the most upper rule has the lowest precedence. And because the former rule is called by the latter one, it means that the function literal is applied before the infix expression, hence the error message.