这是我一直在思考的事情。我经常看到这种模式:
if (pf.isDefinedAt(in)) pf(in)通过将其分解为两个单独的调用,在#isDefinedAt中计算的所有模式也将在#apply中计算。例如:
object Ex1 {
def unapply(in: Int) : Option[String] = {
println("Ex1")
if (in == 1) Some("1") else None
}
}
object Ex2 {
def unapply(in: Int) : Option[String] = {
println("Ex2")
if (in == 2) Some("2") else None
}
}
val pf : PartialFunction[Int,String] = {
case Ex1(result) => result
case Ex2(result) => result
}
val in = 2
if (pf.isDefinedAt(in)) pf(in)哪种打印
Ex1
Ex2
Ex1
Ex2
res52: Any = 2在最坏的情况下,当您的模式最后匹配时,您在调用PartialFunction时已经评估了您的模式/提取器两次。当匹配不只是简单的类或列表模式匹配的自定义提取器时,这可能会变得低效(例如,如果您有一个解析XML文档并返回一些值对象的提取器)
PartialFunction#lift也遭受了同样的双重评价:
scala> pf.lift(2)
Ex1
Ex2
Ex1
Ex2
res55: Option[String] = Some(2)有没有办法有条件地调用一个函数,如果它是定义的,而不可能调用所有的提取器两次?
发布于 2010-11-01 05:30:47
现在在scala-internals邮件列表中就有a conversation going on about this。马丁·奥德斯基提出了一种新的类型:FunctionWithDefault。Martin谈到的不仅仅是运行时的惩罚,还有使用PartialFunction的编译时的惩罚(类文件膨胀
首先,我们需要生成两次模式匹配代码,一次是在
中,另一次是在isDefinedAt中。其次,我们还需要执行代码两次,首先测试函数是否适用,然后实际应用它。
你的问题的答案基本上是肯定的,而且(PartialFunction的)这一行为也不会因为向后兼容性问题而改变(例如,如果isDefinedAt有副作用怎么办)。
提出的新类型FunctionWithDefault没有isDefinedAt,而是有一个方法:
trait FunctionWithDefault[-I, +O] {
def applyOrElse[OO >: O](i : I, default : I => OO) : OO
}它的行为有点像Option的getOrElse方法。
我不得不说,像往常一样,我无法想象这种低效在绝大多数情况下会带来任何形式的性能问题。
https://stackoverflow.com/questions/4064859
复制相似问题