2012-10-04 54 views
10

如何比較兩個斯卡拉功能值是否相等。用例是我有一個列表可以包含重複的列表,我只想執行一次每個函數。如何比較斯卡拉功能值的相等性

如果我有:

scala> object A { 
    | def a {} 
    | } 
defined module A 

scala> val f1 = A.a _ 
f1:() => Unit = <function0> 

scala> val f2 = A.a _ 
f2:() => Unit = <function0> 

如果我嘗試將功能與任何==eq比較,我會在這兩種情況下得到false

scala> f1 == f2 
res0: Boolean = false 

scala> f1 eq f2 
res1: Boolean = false 
+10

這是一個不可解決的問題。 http://en.wikipedia.org/wiki/First-class_function#Equality_of_functions – missingfaktor

回答

15

簡短的回答:這是不可能的。

較長的答案:你可能有某種功能工廠,以確保「相同」的功能是相同的對象。根據您的應用程序的體系結構,這可能不可行。

8

我想對金的回答詳細一點,並舉例說明如何實現函數值的有限可比性。

如果您對函數有某種描述性定義,可以在此描述中檢查相等性。例如,可以以下面的方式定義的簡單的算術函數的類(不是OO類):

sealed trait ArthFun extends (Double => Double) 
case class Mult(x: Double) extends ArthFun {def apply(y: Double) = x * y} 
case class Add(x: Double) extends ArthFun {def apply(y: Double) = x + y} 

採用這種設置,在一個ArthFun由其類和構件所限定,可以檢查是否相等ArthFun類型的值的簡單方法是按案例類定義的對象相等。

scala> trait ArthFun extends (Double => Double) 
defined trait ArthFun 

scala> case class Mult(y: Double) extends ArthFun { def apply(x: Double) = x * y; override def toString = "*" + y} 
defined class Mult 

scala> case class Add(y: Double) extends ArthFun { def apply(x: Double) = x + y; override def toString = "+" + y } 
defined class Add 

scala> Seq(Mult(5),Mult(4),Add(4),Add(3),Mult(5)).distinct 
res4: Seq[Product with ArthFun with Serializable] = List(*5.0, *4.0, +4.0, +3.0) 
+0

我喜歡這個答案,但不喜歡爲每個操作員定義一個類。是否有某種宏魔法可以做到這一點(它將表達式轉換爲具有各種裝飾的類對象,例如平等)。 – user48956