2011-09-08 62 views
3

我已閱讀Difference between method and function in Scala和許多關於方法和功能差異的文章。我感覺'方法'只是一個被定義爲類,特質或對象中方法的「命名函數」。一個'函數'代表這些文章中的「匿名函數」或「函數文字」或「函數對象」之類的東西。一個證據可以在Scala編程http://www.artima.com/shop/programming_in_scala_2ed,第141頁第8.1節中找到,「定義函數的最常見方法是作爲某個對象的成員,這樣的函數稱爲方法。」命名方法和命名函數的定義是什麼?

但是,當我檢查斯卡拉語言參考http://www.scala-lang.org/docu/files/ScalaReference.pdf時,有像命名方法的概念。在頁91,第6.20節返回表達式:「一個返回表達式返回e必須發生在一些名爲 方法或函數的正文內部。」您也可以在同一頁面和其他地方找到術語「命名的功能」。

所以我的問題是,在斯卡拉,方法,命名方法和命名函數是指同一個概念?你在哪裏得到命名函數的定義?

在代碼List(1, 2).map(_ + 1)中,原始表達式_ + 1是一個命名方法,然後將該方法轉換爲函數。什麼樣的函數,匿名函數,函數對象,命名函數?在我的理解,斯卡拉只有兩種類型的函數:一個命名函數是一種方法;一個函數文字的匿名函數。函數文字被編譯到特徵函數N的函數對象中,以便它在純粹的面向Scala的面向對象世界中使用。

但是,對於上述代碼中的常規命名函數/方法(例如_ + 1),爲什麼Scala會將其轉換爲另一個函數對象?

回答

6

在語言級別,只有兩個概念,

  • 方法是斯卡拉的基本構建塊。方法是總是命名。方法生活在課堂或特徵中。方法是JVM的本地構造,因此在Scala和Java中都是相同的。在斯卡拉(不同於功能)的方法可能具有特殊的功能:它們可以在類型參數中抽象出來,他們的觀點可以有默認值或者是隱式的,等等

  • 函數對象只是一個功能特徵的情況下(Function1Function2,...)。該函數在調用函數對象的apply方法時進行評估。定義未命名的「匿名」函數(又名「函數文字」)有特殊的語法。函數只是一個值,因此可以命名(例如,val f: (Int => Int) = (x => x))。 A => B的類型是Function1[A, B]的簡寫。

linked SO question,有人提到一些參考(如Scala的規範)使用詞「功能」不精確爲是指「方法」或「功能對象」。我想部分原因是方法可以自動轉換爲函數對象,這取決於上下文。然而請注意,相反的轉換是沒有意義的:一種方法不是一個一流的值,它以自己的獨立存在存在於堆上。相反,一種方法與它所定義的類別有着千絲萬縷的聯繫。

+0

函數 - >方法轉換是不可避免的,所討論的方法是在函數類中定義的「應用」。非常像我的原始拳擊比喻:) –

+0

我會說不同:每個函數*代表一個函數類的實例上定義的'apply'方法。這裏沒有轉換,這就是函數的定義。另一方面,將一個方法轉換爲一個函數實際上是分配和構建新的東西。 –

+0

我問過這個問題,因爲方法和函數的混合使我困惑 - 是一種函數方法嗎?或命名的功能?或者根本不是功能?這個答案使用了最後一個定義,即一個方法不是一個函數。這個定義在Scala語言規範中是不成立的(參見上面的問題)。這是我試圖澄清的事情。 – Ying

7

到鏈接的問題蓋的回答這個還算不錯,但要滿足您的特定查詢:

  • 方法=>事情你與def關鍵字定義
  • 命名方法=>同樣的,所有方法的名稱爲
  • 命名函數=>已分配給值或從方法轉換的函數。與匿名函數形成對比。

方法和函數之間的區別有點像Java中的int基元和盒裝Integer之間的區別。

在一般的討論中,聽到兩者都被描述爲「整數」是很常見的。這通常不是問題,但是您必須注意確定區別是否與有關。

同樣,當你的程序需要它的時候,一個方法會自動轉換成一個Function(因此也是一個對象),就像裝箱一個原語一樣。所以這不是完全錯誤,指的是作爲一種功能的方法。

UPDATE

那麼它是怎樣工作的?

當您嘗試將方法作爲參數傳遞給例如List[A].map,編譯器將生成一個派生Function1[A,B]的內部類(具有合成名稱)和一個委託給最初提供的方法的apply方法。這個實例將作爲實際參數傳遞。

+0

用於「int」/「Integer」比較的+1。 –

+0

拳擊比較幫助。我知道Scala需要將函數字面量轉換爲FunciontN的方法,因爲Scala是一種OO語言。但是,如果您提供map爲常規對象方法,爲什麼Scala會將方法「框」到另一個方法中? – Ying

+0

一個方法永遠不會被「裝箱」到另一個方法中,而只會被放入一個函數中。當您將方法指定爲例如'List [A] .map',它實際上是作爲函數'A => B'傳遞的。在內部,map方法將在提供的函數實例上調用'apply',然後調用您指定的方法。 –

相關問題