Как сравнить Scala значения функции для равенства

Как вы можете сравнить два значения функции 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

Ответ 1

Короткий ответ: Это невозможно.

Более длинный ответ: у вас может быть какая-то функция factory, которая гарантирует, что "идентичные" функции являются общими для одного и того же объекта. В зависимости от архитектуры вашего приложения это может оказаться невыполнимым.

Ответ 2

Я хочу немного рассказать о Ким и дать пример того, как добиться ограниченной сопоставимости значений функций.

Если у вас есть какое-то описательное определение вашей функции, можно проверить равенство в этом описании. Например, вы можете определить класс (а не класс оо) простых арифметических функций следующим образом:

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 просто по равенству объекта, как определено классом 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)