面嚮對象語言(如Java的)通常具有類以及有方法,雖然功能不是「一等公民」,這意味着你不能將一個函數直接分配給一個變量,或者將一些函數放在一個列表中,或者將它們作爲參數發送給其他函數。 如果你想在java中發送一個函數,你必須用一個方法創建一個類併發送這個類。 舉例來說,如果你想有一個計算其輸入的雙重功能,你必須把它放在一類,像這樣:
class Doubler
{
public int apply(int a)
{
return a * 2;
}
}
在函數式編程語言,比如Haskell,函數是「第一類「,你可以將它們存儲在變量中併發送給它們。
doubleIt :: Integer -> Integer
doubleIt x = 2 * x
作爲一個功能和麪向對象的美麗組合,scala同時具有方法和函數。
// a function like in haskell
val doubleIt = (x:Int) => x * 2
// a method in an object like in java
object Doubler {
def apply(x:Int) = x * 2
}
在scala def
總是定義一個方法。請注意,REPL將您在對象中寫入的所有內容封裝爲main
(爲了能夠在運行中編譯和執行),但編寫不包含在程序中的類/對象/特徵中的def something
將無法編譯。
斯卡拉還提供了一些額外的優惠,以減少對象和一流功能之間的脫節。
首先,scala中的Doubler
對象定義在那裏的「apply」方法有點神奇。 鑑於上面的定義,你可以寫Doubler(2)
和scala的編譯器將它轉換成Doubler.apply(2)
並愉快地返回4.因此你可以使用對象作爲函數進行排序。你也可以(通過在方法調用後放一個_符號)將該方法轉換爲一個真實函數並(比如說)將它分配給一個val。
scala> val d = Doubler.apply _
d: Int => Int = <function1>
scala> d(2)
res1: Int = 4
在另一方面,斯卡拉的方式使得像val doubleIt = (x:Int) => x * 2
功能劃分爲第一類「東西」就是把它弄成這個樣子你背後。
object Doubler extends Function[Int, Int] {
def apply(x: Int) = x*2
}
val doubleIt = Doubler
所以,是的...一個函數實際上仍然是一個方法類,或多或少像在java中一樣。除了scala爲你做,並且會給你大量的語法糖來使用生成的類,就像你使用實際的函數一樣。
爲了讓事情變得更有趣,因爲函數是一流的,您可以在scala中使用它們做的一件事就是將它們用作其他函數或方法的返回值。 所以當你寫def a : (Int, Int) => Int = {(s:Int, t:Int) => s + t}
時,你實際上定義了一個方法,叫做a
,它返回一個函數。它可能會在第一次(第二次,第三次......)時產生混淆,但是第四次左右可能會開始看起來很漂亮。至少這就是它爲我做的。
問題從「有兩種定義函數的方式」開始。重複(其中之一)以「定義函數的兩種方式」開頭。這不是郵件列表,它是問題和答案的數據庫。用它! – 2012-03-27 17:47:06
@ DanielC.Sobral是對的。我希望在開始寫回答之前,我已經檢查過了,但實際上還有其他問題,涵蓋了與此相同的理由。 – 2012-03-27 17:58:59