2012-10-04 8 views
10

Come si possono confrontare due valori di funzione Scala per l'uguaglianza. Il caso d'uso è che ho una lista di funzioni in cui l'elenco può contenere duplicati e voglio solo eseguire ciascuna funzione una sola volta.Come confrontare i valori della funzione Scala per l'uguaglianza

Se ho:

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

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

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

Se provo a confrontare la funzione sia con == o eq, mi metterò false in entrambi i casi:

scala> f1 == f2 
res0: Boolean = false 

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

È un problema indecidibile in generale. http://en.wikipedia.org/wiki/First-class_function#Equality_of_functions – missingfaktor

risposta

15

Risposta breve: Non è possibile.

Risposta più lunga: è possibile avere una sorta di fabbrica di funzioni che garantisce che le funzioni "identiche" siano acutalmente lo stesso oggetto. Tuttavia, a seconda dell'architettura dell'applicazione, potrebbe non essere fattibile.

8

Voglio dare un po 'di spazio alla risposta di Kim e dare un esempio di come ottenere una comparabilità limitata dei valori delle funzioni.

Se si dispone di una sorta di definizione descrittiva della propria funzione, è possibile verificare l'uguaglianza in questa descrizione. Ad esempio, è possibile definire una classe (non una classe oo) di funzioni aritmetiche semplici nel seguente modo:

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} 

Con questa configurazione, in cui un ArthFun è definita dalla sua classe e membri, è possibile verificare l'uguaglianza di valori del tipo ArthFun semplicemente per l'uguaglianza dell'oggetto definita dalla classe case.

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

Mi piace questa risposta, ma non mi piace dover definire una classe per ogni operatore. Esiste una sorta di magia macro che potrebbe fare ciò (trasforma le espressioni in oggetti di classe con varie decorazioni, come l'uguaglianza). – user48956

Problemi correlati