2014-08-29 62 views
3

我正在閱讀Scala編程的書。在本書中,它表示「函數文本被編譯成一個類,當在運行時實例化時它是一個函數值」。它提到「函數值是對象,所以如果你喜歡,你可以將它們存儲在變量中」。Scala中函數的平等是Scala中的函數對象嗎?

所以我嘗試檢查功能之間的平等。但我失敗了。

  1. 如果函數是Scala中的對象,那麼它的行爲應該和Scala中的其他對象一樣。也許檢查功能的平等是沒有意義的,所以它被禁用?

  2. 將函數編譯成Scala中的對象嗎?

+0

我能解決這個問題的一些領域。我已經介紹了我發現的內容,並將其發佈爲另一個相關的StackOverflow問題的答案。你可以在這裏找到它:http://stackoverflow.com/a/34909554/501113 – chaotic3quilibrium 2016-01-20 20:15:50

+1

@ chaotic3quilibrium謝謝,當我提出這個問題時,我腦海裏想的是,如果函數是scala中的對象,那麼是否可以定義像'equalTo'或'equals'來檢查兩個函數值的相等性(不限於檢查參考的相等性)。現在,似乎只能檢查函數值引用的相等性。 – 2016-01-22 01:40:40

回答

7

Lambda被編譯爲匿名類(不是case類,據我記憶)。這意味着,如果你這樣做:

val f1: (String) => String = _ => "F1" 
val f2: (String) => String = _ => "F2" 

兩個f1f2Function1[String,String]亞型,但兩者是不同匿名類的,所以不能相等。

如果你把它寫成:

case class F(res: String) extends ((String) => String) { 
    def apply(s: String) = res 
} 

然後:

val f1: (String) => String = F("A") 
val f2: (String) => String = F("A") 
f1 == f2 // true 
+0

但是,如果我使用以下代碼:def f1(a:String):String =「F1」; def f2(a:String):String =「F2」; f1 == f2 ;.在語句f1 == f2處,出現錯誤:不適用於(String)。上述代碼與你的有什麼區別? – 2014-09-04 02:21:04

+0

再一次要做的是通過2個不同的匿名類來實現trait'Function [String,String]'。沒有什麼能夠幫助編譯人員在語義上知道他們是平等的。 – cchantep 2014-09-04 07:20:29

+1

這不是我得到的錯誤。我得到了「錯誤:缺少方法f1的參數;'」和「錯誤:缺少方法f2的參數;'」,這是有道理的:你定義了兩個*方法*(不是函數,函數和方法完全不同) ,'f1'和'f2'都帶有一個'String'類型的參數,但是你用* no *參數調用它們,然後嘗試比較調用它們的結果。 – 2014-09-04 08:05:35

4

目前尚不清楚是什麼功能的 「平等」 的意思。通常,人們關心的是「這兩個函數計算相同的結果嗎?」

然而,這是一個衆所周知的不可解決的問題,功能問題。實際的證明顯然更爲複雜,但一個簡單的直覺是:如果你能分辨出兩個函數是否相等,那麼你可以通過詢問「這個函數是否等於while (true) {}?」來解決暫停問題。

所以,我們不能決定兩個函數是否計算出相同的結果。例如,我們可能做的是,例如,檢查它們是否包含完全相同的代碼。但這很無聊。只是一些微小的編譯器優化或重命名單個變量會使直觀上兩個函數應該相等並不相等。

人類,我們採取簡單的方法:兩個功能是相等的,如果它們是相同的,否則它們不是。

+0

我認爲關於函數的「平等性」可能是這樣的:將函數想象爲將一個值空間映射到另一個值空間的規則,如果兩個函數擁有相同的規則,那麼它們是相等的。但我認爲現在編譯器不可能做到這一點。 我真的感到困惑的是,在我回復applicius的答案時,這是關於Scala中函數和方法的語法和概念。 – 2014-09-04 02:24:16

+0

「編譯器現在無法做到這一點。」 - 不,這是不可能的。事實證明,這是不可能的,不會隨着技術而改變。 *函數問題*是不可判定的,並且在時間結束之前它將保持不可判定。 – 2014-09-04 08:07:52

+0

感謝功能問題和解釋,我想我需要回顧功能和方法的概念。 – 2014-09-04 13:42:17