Scala方法调用语法疑问:foldLeft与{}、()用法解析
问题解答
1. 关于代码中r和l的类型疑问
先拆解你写的代码里的语法陷阱:
val r = List(1, 2, 3).foldLeft(0) _+_
这段代码的语法解析和你预期的完全不一样!Scala的运算符优先级和占位符_的作用在这里产生了歧义:
- 你可能以为是把
foldLeft(0)和_+_(即(a,b) => a+b)结合,但实际上,foldLeft(0) _是部分应用函数——它表示只传入foldLeft的第一个参数0,返回一个等待第二个参数(即累加函数(Int,Int)=>Int)的函数,类型是((Int, Int) => Int) => Int。 - 而后面的
+_被解析成了字符串拼接的匿名函数:因为Scala中函数的toString方法会返回类似$Lambda$xxx@xxx的字符串,当你写(foldLeft(0) _) + _时,_是参数占位符,整个表达式等价于:
这就是为什么val r = (x: String) => (List(1,2,3).foldLeft(0) _).toString + xr的类型是String => String——它是一个接收字符串、返回函数字符串和输入字符串拼接结果的函数。
再看第二行:
val l = r{"hello"}
这里的r{"hello"}其实等价于r("hello")(Scala中,当方法/函数只有一个参数时,可以用大括号代替括号),所以调用r时传入了"hello",返回的是(foldLeft(0) _)的字符串表示加上"hello",也就是你看到的$Lambda$1643/1458648440@23ae6386hello——l根本不是函数,而是一个字符串,自然无法调用。
如果你的真实意图是用foldLeft计算累加和,正确的写法应该是:
// 两种正确写法 val sum1 = List(1,2,3).foldLeft(0)(_+_) val sum2 = List(1,2,3).foldLeft(0){_+_}
2. Scala中()和{}的官方参考文档
Scala官方有明确的文档说明两者的区别和使用场景:
- Scala语言规范(Scala Language Specification):在"Expressions"章节里,详细定义了括号表达式(Parenthesized Expressions)和块表达式(Block Expressions)的语法规则,包括方法调用时参数列表的括号与大括号的差异——比如块表达式可以包含多行代码、声明变量等,而括号里只能是单个表达式。
- Scala风格指南(Scala Style Guide):专门有一节讲解何时使用括号、何时使用大括号:
- 当方法接收单个匿名函数参数时,优先用大括号(尤其是函数体有多行时);
- 当方法参数是多个值或简单表达式时,用括号;
- 无参数的方法,如果是纯函数(无副作用)可以省略括号,有副作用(比如打印、修改状态)则建议保留括号。
内容的提问来源于stack exchange,提问作者WesleyHsiung
相关产品推荐
相关产品推荐

