2012-12-14 28 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時,你會編寫和閱讀很多這樣的代碼。

乾杯!