很可能要知道某个函数是否在某个时刻被定义,必须完成计算其值的重要部分。在一个PartialFunction
,执行时isDefined
and apply
,两种方法都必须这样做。这份普通的工作成本高怎么办?
有可能缓存它的结果,希望在isDefined之后调用apply。绝对是丑陋的。
我常常希望PartialFunction[A,B]
将会Function[A, Option[B]]
,这显然是同构的。或者,也许还有另一种方法PartialFunction
, say applyOption(a: A): Option[B]
。对于某些 mixins,实现者可以选择实现 isDefined 和 apply 或 applyOption。或者所有这些都是为了安全起见,性能明智。测试的客户isDefined
鼓励在调用 apply 之前使用applyOption
反而。
然而,事实并非如此。库中的一些主要方法,其中collect
在集合中需要一个PartialFunction
。是否有一种干净(或不太干净)的方法来避免为 isDefined 和 apply 之间重复的计算付费?
还有,就是applyOption(a: A): Option[B]
方法合理吗?在未来的版本中添加它听起来可行吗?值得吗?
为什么缓存会出现这样的问题?在大多数情况下,您有本地计算,因此只要为缓存编写一个包装器,就不必担心它。我的实用程序库中有以下代码:
class DroppedFunction[-A,+B](f: A => Option[B]) extends PartialFunction[A,B] {
private[this] var tested = false
private[this] var arg: A = _
private[this] var ans: Option[B] = None
private[this] def cache(a: A) {
if (!tested || a != arg) {
tested = true
arg = a
ans = f(a)
}
}
def isDefinedAt(a: A) = {
cache(a)
ans.isDefined
}
def apply(a: A) = {
cache(a)
ans.get
}
}
class DroppableFunction[A,B](f: A => Option[B]) {
def drop = new DroppedFunction(f)
}
implicit def function_is_droppable[A,B](f: A => Option[B]) = new DroppableFunction(f)
然后如果我有一个昂贵的计算,我会编写一个函数方法A => Option[B]
并做类似的事情(f _).drop
将其用于收集或其他用途。 (如果您想内联执行此操作,您可以创建一个方法,该方法需要A=>Option[B]
并返回部分函数。)
(相反的变换——从PartialFunction
to A => Option[B]
--称为提升,因此称为“下降”;我认为“unlift”是一个更广泛使用的相反操作术语。)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)