scala 检查按名称传递参数的结构相等性

zvokhttg  于 5个月前  发布在  Scala
关注(0)|答案(2)|浏览(53)

是否有一种方法来比较按名称传递参数是否相等?

case class Comp[A](f: () => A)
def delay[A](compute: => A) = Comp(() => compute)

def deterministic(x: Int) = x + 1

val comp1 = delay(deterministic(1))
val comp2 = delay(deterministic(1))

println(comp1 == comp2) // Returns false

字符串
我知道当传递的计算包含副作用时,这可能没有意义,但我希望这是出于缓存/记忆化的目的,并且假设传递的计算是纯计算。
我可以用一个 Package 器类来实现这一点,该 Package 器类分别接受函数和参数,但是,对于我想要实现的API的用户来说,它看起来并不干净。
我想做的事情是扩展scala.util.control.TailCalls,这样代码看起来就像

def fib(n: Int): TailRec[Int] =
  if (n < 2) done(n) else for {
    x <- tailcallMemoized(fib(n - 1))
    y <- tailcallMemoized(fib(n - 2))
  } yield x + y


它使用户能够执行计算与记忆的结果

w3nuxt5m

w3nuxt5m1#

别名参数是伪装的函数。
从数学上讲,如果两个函数对相同的输入返回相同的值,那么它们是相等的。(没有额外的假设)等于一个算法,因为停机问题。你只能手动分析一些特殊情况,或者将函数的表达方式限制在可能的表示的某个子集上,这样的证明是可能的,并且是随机的,name param不以这种方式约束。
然而,你可以做一些假设,假设函数是纯函数,那么这个函数就是一个伪装的(): Unit函数,它只接受一个可能的值作为输入,所以它只能有可能的输出。
然后,您可以调用这些按名称的函数中的每一个,比较结果,并基于此决定它们是否相等。(然后你可以缓存输出)以了解它返回的内容,所以你可能想分析一下是否通过-name毕竟提供了一个实际的好处。也许你想要的是像Shapeless中的Lazy或Cats中的Eval这样的东西,让计算变得懒惰但记忆化。
当然,如果这样的代码将与一个副作用函数/by-name一起使用,那么事情可能会变得很糟糕,所以你可能想要记录它。

cnjp1d6j

cnjp1d6j2#

您可以覆盖case类强制参数的equals

case class Comp[A](f: () => A) {
  override def equals(obj: Any): Boolean = obj match {
    case Comp(f1) => f() == f1()
    case _        => false
  }
}

个字符

相关问题