2012-12-14 33 views
12

我总是想知道为什么有时使用函数文字我们甚至可以忽略大括号,即使对于多个语句。为了说明这一点,多行函数文字的语法是用大括号括住语句。像这样,多行函数字面量作为Scala中的参数

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 
} 

上面的代码更具可读性,我注意到很多示例都使用这种语法。但是,有没有我可能错过的特殊规则,来解释为什么这是按预期工作的?

回答

20

只有几个简单的语法规则。规范的附录值得一读。

函数文字或匿名函数(6.23)将分别看起来像x => Exprx => 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中具有函数字面量(它只是一个语句序列,不需要大括号)。

这里,很明显的是,匿名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 
+0

这是我一直在寻找的解释。另外,除了突出显示的规格部分之外,还可以参考块(6.11)部分以便更好地理解。 – jafaeldon

+0

Geat答案,我无法更好地解释它。 Upvoted它。干杯! – wleao

8

这是使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不是单位的成员可能的原因:分号是 在'value 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时,你会编写和阅读很多这样的代码。

干杯!