如何比较Scala函数值的相等性

13
如何比较两个Scala函数值的相等性。使用场景是,我有一个包含重复项的函数列表,我只想执行每个函数一次。
如果我有:
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
2个回答

16

简短回答:不可能。

更长的回答:您可以拥有某种函数工厂,确保“相同”的函数实际上是相同的对象。但根据您的应用程序架构,这可能并不可行。


8

我希望进一步解释Kim的答案,并且给出一个例子来说明如何实现有限的函数值可比性。

如果你对这个函数有某种描述性定义,那么可以在此描述上检查相等性。例如,你可以按照以下方式定义简单算术函数的类(不是面向对象的类):

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)

我喜欢这个答案,但不喜欢为每个运算符定义一个类。有没有一些宏魔法可以做到这一点(将表达式转换为带有各种修饰的类对象,例如相等性)? - user48956

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接