2013-06-20 76 views
4

根據我的理解,部分應用的函數是函數,我們可以在不傳遞所有/一些必需參數的情況下調用函數。Scala中缺少所有參數的部分應用函數

def add(x:Int, y:Int) = x + y 
val paf = add(_ :Int, 3) 
val paf1 = add(_ :Int, _ :Int) 

在上面的例子中,PAF1是指所有的參數丟失,我可以調用使用到部分應用功能:paf1(10,20)和原有功能可以使用add(10,20)

我的問題是被調用,什麼是由於調用語法幾乎相同,創建缺少所有參數的部分應用函數的額外好處是什麼?只是將方法轉換爲一流的功能?

回答

6

Scala的def關鍵字是你如何定義方法和方法不功能(Scala中)。因此,您的add不像您的paf1那樣是一流的函數實體,即使它們在生成結果時對它們的參數的語義等價。

斯卡拉將自動使用部分應用程序打開的方法成等價的功能,您可以通過擴展你的例子有點看:

def add(x: Int, y: Int) = x + y 
... 
val pa2: (Int, Int) => Int = add 
pa2: (Int, Int) => Int = <function2> 

這可能在這個例子似乎沒有什麼好處,但在許多如果有非顯式約束指示需要函數(或者更準確地說,在其他地方明確指定的約束),那麼您可以在需要函數的地方給出(類型兼容)方法名稱。

1

我相信其他人可以綜合一堆用於此的用例,但實際上這只是函數是值的結果。如果你不能像正常值那樣傳遞一個函數,那將是非常奇怪的。

斯卡拉處理這個東西有點笨拙。部分應用通常與咖喱相結合。我認爲這是一個怪癖,你基本上可以使用_來擴展任何表達式。通過編寫add(_ : Int, _ : Int),你有效地做了什麼(模仿斯卡拉圍繞柯里化的句法怪癖)正在寫作(x : Int) => (y : Int) => add(x, y)。我相信你可以想到後一個定義在程序中可能有用的情況。

2

更新:問題是,爲什麼我會想要一個eta擴展的方法?斯卡拉聖經中的一個偉大的修辭策略是他們引導你在許多頁面上的例子。我採用了下面的Exodus隱喻,因爲我剛剛看到了Charlton Heston的「十誡」。我並不假裝這個答案比Randall的解釋更具說服力。

您可能需要有人用較小的代表值得注意的是,大積聚在出埃及記聖經的書是:

http://www.artima.com/pins1ed/first-steps-in-scala.html#step6

args foreach println

的「第一步」中的前一步驟,着實

args foreach (arg => println(arg))

但我猜沒有人做,如果類型推斷神是那種方式。

從規範中的更改日誌中:「部分未應用的方法現在被指定爲m _而不是前面的表示法& m的 」。也就是說,在某個點上,「函數ptr」的概念成爲了一個沒有參數提供的部分函數。這是什麼。更新:「比喻性」。

+1

現在我知道人們總是在評論:「老兄,怎麼了?」這意味着「沒用」。你沒有從這個答案得到一點信息?我當然不知道曾經是一個喚起&m的語法。 (當然,直到現在。) –

2

方法函數有區別。

例如,如果您看一下List.map的聲明,它確實需要一個函數。但是Scala編譯器足夠聰明,可以接受這兩種方法和功能。

引自here

這一招......對於強迫的方法到一些地方的函數的預期,是很容易的,即使是編譯器可以檢測並做到這一點。事實上,這種自動強制有一個自己的名字 - 這就是所謂的Eta擴張。

另一方面,看看Java 8;據我所知,這並不容易。