首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PartialFunction设计是否低效?

PartialFunction设计是否低效?
EN

Stack Overflow用户
提问于 2010-11-01 04:00:18
回答 1查看 1.1K关注 0票数 13

这是我一直在思考的事情。我经常看到这种模式:

代码语言:javascript
复制
if (pf.isDefinedAt(in)) pf(in)

通过将其分解为两个单独的调用,在#isDefinedAt中计算的所有模式也将在#apply中计算。例如:

代码语言:javascript
复制
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)

哪种打印

代码语言:javascript
复制
Ex1
Ex2
Ex1
Ex2
res52: Any = 2

在最坏的情况下,当您的模式最后匹配时,您在调用PartialFunction时已经评估了您的模式/提取器两次。当匹配不只是简单的类或列表模式匹配的自定义提取器时,这可能会变得低效(例如,如果您有一个解析XML文档并返回一些值对象的提取器)

PartialFunction#lift也遭受了同样的双重评价:

代码语言:javascript
复制
scala> pf.lift(2)
Ex1
Ex2
Ex1
Ex2
res55: Option[String] = Some(2)

有没有办法有条件地调用一个函数,如果它是定义的,而不可能调用所有的提取器两次?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-11-01 05:30:47

现在在scala-internals邮件列表中就有a conversation going on about this。马丁·奥德斯基提出了一种新的类型:FunctionWithDefault。Martin谈到的不仅仅是运行时的惩罚,还有使用PartialFunction的编译时的惩罚(类文件膨胀

首先,我们需要生成两次模式匹配代码,一次是在

中,另一次是在isDefinedAt中。其次,我们还需要执行代码两次,首先测试函数是否适用,然后实际应用它。

你的问题的答案基本上是肯定的,而且(PartialFunction的)这一行为也不会因为向后兼容性问题而改变(例如,如果isDefinedAt有副作用怎么办)。

提出的新类型FunctionWithDefault没有isDefinedAt,而是有一个方法:

代码语言:javascript
复制
trait FunctionWithDefault[-I, +O] {
  def applyOrElse[OO >: O](i : I, default : I => OO) : OO
}

它的行为有点像OptiongetOrElse方法。

我不得不说,像往常一样,我无法想象这种低效在绝大多数情况下会带来任何形式的性能问题。

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4064859

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档