2012-09-21 102 views
1

我基本上是新功能編程和scala,下面的問題可能看起來很愚蠢。函數文字 - 需要幫助理解代碼片段

val f = (a:Int) => a+1 

在上面的代碼中,我應該考慮f是一個函數或變量?來自C/C++的背景,首先想到的是f是一個存儲匿名函數返回值的變量,但我認爲這不是解釋它的正確方法。任何解釋都會非常有用。

(一些我上面使用可能是錯相對於階/功能編程,術語的麻煩與它承擔)

回答

5

這裏,f是存儲函數的變量。這是自說任何以下的真的沒有不同:

val a = 4    // `a` is a variable storing an Int 
val b = "hi"   // `b` is a variable storing a String 
val f = (a:Int) => a+1 // `f` is a variable storing a function 

您也可以使用REPL證實了這一點:

scala> val f = (a:Int) => a+1 
f: Int => Int = <function1> 

因此,這是告訴你,f有型Int => Int。換句話說,f是一個函數,它帶有一個參數Int,並返回一個Int

由於f是一個變量,你可以調用它的方法,或者作爲參數傳遞給期待它的類型功能:

a + 3 // here I'm calling the `+` method on `a`, which is an Int 
f(3) // here I'm calling the `apply` method on `f`, which is a function `Int => Int` 
f(a) // the function `f` expects an `Int`, which `a` is 
(1 to 3).map(f) // the `map` method expects a function from Int to Int, like `f` 
+0

不要說「變量」,這很混亂。這是一個價值,你不能用任何新的價值來覆蓋它。術語「變量」應該保留爲「var」,值應該用於「val」。它只是一個__place-holder__意義上的變量,這可能就是你的意思。 –

+2

@ 0__:Scala規範使用單詞「變量」,即使值無法更改,Haskell規範也是如此,幾乎所有的數學教科書都是如此,等等。您可能認爲標準用法可能會引起混淆,但嘗試改變它不是一場你將要贏得的戰鬥。 –

+0

@Travis,同意。 – dhg

1

是的,像DHG說,f是一個變量(即可以」不能改變)存儲一個函數。

但是,這裏有一個細微之處:

...出現的第一個念頭是,f是存儲的匿名函數的 返回值

f實際存儲的變量函數,不是結果。所以你可以給它不同的輸入,並得到不同的輸出。所以,你可以使用它像f(7)然後f(5)。 Scala中的函數是對象,因此可以分配給變量,作爲參數傳遞等。

I recently posted about function literals,這可能對您有所幫助。

0

f是值表示函數文字。

在聲明中,右側是函數文字。左側將其綁定到一個名稱,該名稱隨後稱爲val關鍵字與LISP中的let類似)。現在該函數與符號f相關聯,因此您可以使用此符號f來引用該函數。

我不同意其他答案暗示f應該被稱爲變量。f是一個值,因爲它固定在確定的右側項目不能更改。與此相反的變量,與var介紹,讓你重新賦值給一個符號:

var f = (i: Int) => i + 1 

var開頭的變量定義,f是名稱或變量的符號,有可能是一個可選: ...定義了變量的類型(如果不填寫,類型將自動從作業推斷出),並且= ...定義值最初的分配給該變量。

所以,當一個人說,不要用數字常量混淆,它只是不改變的實體。一個函數也可以是一個值,因爲f然後總是表示這個相同的函數,即使您可以用不同的參數來提供該函數,這些參數會產生不同的結果。

現在用var你可以重新分配其右手邊:

f(2) // --> 3 
f = (i: Int) => i * 2 // assign a new function to the variable f. 
f(2) // --> 4 

函數式編程是所有關於避免變量(重新分配)。


也可以定義一個函數,而根本不會將它分配給一個值或一個變量。下面定義了這樣的功能,並立即用參數4稱之爲:

{ i: Int => i + 1 } apply 4 // --> 5 

儘管這是作爲一個說法本身很少有用,但調用期望一個函數參數的方法時,你會看到「純」的功能往往。例如

val s = List(1, 2, 3) 
s.map { (i: Int) => i + 1 } // --> List(2, 3, 4) 
s.map { _ + 1 }    // equivalent 
s.map(_ + 1)    // equivalent 
+0

帶上一粒鹽;正如在上面的評論中提到的那樣,即使在文獻中,'val'和'var'通常都被稱爲變量,可能使用「一次寫入」或「不變變量」來區分前者和後者。 –