2012-10-04 33 views
10

¿Cómo se pueden comparar dos valores de función de Scala para la igualdad. El caso de uso es que tengo una lista de funciones donde la lista puede contener duplicados y solo deseo ejecutar cada función una vez.Cómo comparar los valores de función de Scala para la igualdad

Si tengo:

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

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

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

Si intento de comparar la función, ya sea con == o eq, voy a tener false en ambos casos:

scala> f1 == f2 
res0: Boolean = false 

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

Es un problema indecidible en general. http://en.wikipedia.org/wiki/First-class_function#Equality_of_functions – missingfaktor

Respuesta

15

Respuesta corta: No es posible.

Respuesta más larga: Puede tener algún tipo de fábrica de funciones que garantice que las funciones "idénticas" sean realmente el mismo objeto. Dependiendo de la arquitectura de su aplicación, eso podría no ser factible.

8

Quiero extenderme un poco sobre la respuesta de Kim y dar un ejemplo de cómo lograr una comparabilidad limitada de los valores de las funciones.

Si tiene algún tipo de definición descriptiva de su función, es posible verificar la igualdad en esta descripción. Por ejemplo, puede definir una clase (no es una clase oo) de funciones aritméticas simples de la siguiente manera:

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 esta configuración, donde un ArthFun se define por su clase y los miembros, se puede comprobar la igualdad de valores del tipo ArthFun simplemente por igualdad de objeto como se define en la clase de caso.

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

Me gusta esta respuesta, pero no me gusta tener que definir una clase para cada operador. ¿Hay algún tipo de macro magia que podría hacer esto (convierte las expresiones en objetos de clase con varias decoraciones, como la igualdad). – user48956

Cuestiones relacionadas