我总是想知道为什么有时使用函数文字我们可以忽略大括号,即使对于多个语句也是如此。为了说明这一点,多行函数文字的语法是用大括号括起语句。像这样,
val fl = (x: Int) => {
println("Add 25 to "+x)
x + 25
}
但是,当您将其传递给单参数函数时,可以忽略函数文字所需的大括号。
因此,对于给定的函数f,
def f( fl: Int => Int ) {
println("Result is "+ fl(5))
}
您可以像这样调用f(),
f( x=> {
println("Add 25 to "+x)
x + 25
})
-------------------------
Add 25 to 5
Result: 30
或者在函数调用中使用花括号而不是括号时,可以从函数文字中删除内部花括号。所以下面的代码也可以使用,
f{ x=>
println("Add 25 to "+x)
x + 25
}
上面的代码更具可读性,我注意到很多例子都使用这种语法。但是,是否有任何我可能错过的特殊规则,以解释为什么这样做符合预期?
答案 0 :(得分:24)
只有几个简单的语法规则。该规范的附录值得细读。
函数文字或匿名函数(6.23)看起来像x => Expr
或x => Block
,具体取决于上下文是Expr还是ResultExpr。
功能应用程序(6.6)看起来像f(Expr, Expr)
或f BlockExpr
,即f{ Block }
。也就是说,BlockExpr只是{...}
内的一系列块语句。
当你致电f(g)
时,g是一个Expr,所以作为一个函数文字,x => Expr
。 Expr可以是BlockExpr,x => { ... }
。
当你调用f{ Block }
时,f { x => ... }
在块的ResultExpr中有函数文字(这只是一系列语句,不需要大括号)。
在这里,很明显anon func位于一个块的底部:
scala> def m(x: Int=>Int) = x(5)
m: (x: Int => Int)Int
scala> m {
| val y = 7
| x => // no brace
| x+y+1
| }
res0: Int = 13
答案 1 :(得分:11)
这是让Scala对我很漂亮的事情之一。
您问题的简单答案是:
圆括号()用于单行构造。例如,这有效:
def f(fl: Int => Int) {
println("Result is " + fl(5))
}
f(
x =>
x + 25)
f(x => x + 25) // single line
和花括号{}用于多行语句。例如,这有效:
f {
x =>
println("Add 25 to " + x)
x + 25
}
但此代码不起作用:
f (
x =>
println("Add 25 to " + x)
x + 25
)
编译器抱怨以下消息:
值x不是单位可能原因的成员:也许是分号 在'值x'之前丢失?
如果添加分号,则会出现由不匹配的括号引起的语法错误。
如果您尝试这样做:
f { x => println("Add 25 to " + x) x + 25 }
编译器将通过以下消息回复您:
value x is not a member of unit
你是否认为他正试图找到x作为单位成员。喜欢:
f { println("Add 25 to " + x).x.+(25) }
这显然是错误的。
如果你添加内花括号,像这样:
f (
x => {
println("Add 25 to " + x)
x + 25
}
)
这也可以,但你仍然有一个多线语句,通过使用花括号来表示。因此编译器知道你想要首先打印什么,然后将25添加到x。
我之前被这些微妙之处所困扰。从那以后,我一直在关注我用这些编码的方式,因为当你主要使用地图,flatMaps,foreachs,fors和currying时,你会编写代码并阅读很多内容。
干杯!