Scala 部分功能设计是否低效?

Scala 部分功能设计是否低效?,scala,functional-programming,scala-2.8,Scala,Functional Programming,Scala 2.8,这是我想了一段时间的事情。我经常看到这种模式: 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 un

这是我想了一段时间的事情。我经常看到这种模式:

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文档并返回一些值对象)

部分功能#升降机受到相同的双重评估:

scala> pf.lift(2)
Ex1
Ex2
Ex1
Ex2
res55: Option[String] = Some(2)
如果函数已定义,有没有一种方法可以有条件地调用它,而不必潜在地调用所有提取器两次?

scala internals邮件列表中现在有一种方法。Martin Odersky提出了一种新类型:
函数带默认值
。Martin不仅谈到使用
PartialFunction的运行时代价,还谈到编译时代价(类文件膨胀):

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

您的问题的答案基本上是“是”,并且这种行为(对于
PartialFunction
)也不会因为向后兼容性问题而改变(例如,如果
定义为
会产生副作用怎么办)

正在提出的新类型,
function with default
没有
定义为
,并且有一个方法:

trait FunctionWithDefault[-I, +O] {
  def applyOrElse[OO >: O](i : I, default : I => OO) : OO
}
它的行为有点像
选项
s
getOrElse
方法


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

谢谢您的详细回复!FunctionWithDefault听起来正是我想要的。如果在性能关键代码中有复杂的匹配语句,那么两次模式匹配肯定会对性能造成很大影响!如果
default
是按名称传递的,那么这比返回选项更有效率吗?也许我应该阅读scala内部代码。我把默认值的符号搞错了,很奇怪,它是一个
I=>OO
当前scala编译器为
PartialFunction
文本生成的
getOrElse
。我认为我们应该始终使用该方法,并且不应该手动调用
isDefined
。对于<代码>部分函数在模式匹配中,考虑将其转换为提取器: