2012-03-27 100 views
1

可能重複:
Difference between method and function in Scala
Two ways of defining functions in Scala. What is the difference?定義斯卡拉功​​能不同

有2種方式來定義一個函數。

scala> def a : (Int, Int) => Int = {(s:Int, t:Int) => s + t} 
a: (Int, Int) => Int 

scala> a 
res15: (Int, Int) => Int = <function2> 

scala> def b(s:Int, t:Int) : Int = s+t 
b: (s: Int, t: Int)Int 

scala> b 
<console>:9: error: missing arguments for method b in object $iw; 
follow this method with `_' if you want to treat it as a partially applied function 
       b 
      ^

scala> b(3,4) 
res17: Int = 7 

scala> a(3,4) 
res18: Int = 7 

在我如何定義函數a和b有什麼區別嗎?爲什麼我在b中缺少參數錯誤?

+0

問題從「有兩種定義函數的方式」開始。重複(其中之一)以「定義函數的兩種方式」開頭。這不是郵件列表,它是問題和答案的數據庫。用它! – 2012-03-27 17:47:06

+0

@ DanielC.Sobral是對的。我希望在開始寫回答之前,我已經檢查過了,但實際上還有其他問題,涵蓋了與此相同的理由。 – 2012-03-27 17:58:59

回答

6

b不是一個函數,而是一個方法。您可以通過在編譯器中添加_來將b轉換爲函數。 val f = b _。但是,如果您想將對象的方法傳遞給以函數作爲參數的方法/函數,則只應該這樣做。如果你只是想按照正常的方式定義一個函數。

但是,爲了回答你的問題,還有另一種方式:

val f = new Function2[Int,Int,Int] { 
    def apply(x: Int, y: Int) = x + y 
} 
2

面嚮對象語言(如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,它返回一個函數。它可能會在第一次(第二次,第三次......)時產生混淆,但是第四次左右可能會開始看起來很漂亮。至少這就是它爲我做的。