问题描述
这是我一段时间想知道的。我看到这种模式很多:
if(pf.isDefinedAt(in))pf(in)
code>
通过将其分解为两个单独的调用,所有在#isDefinedAt中评估的模式都将在#apply中进行评估。例如:
object Ex1 {
def unapply(in:Int):Option [String] = {$ b如果(在== 1中)一些(1)else无
}
}
对象Ex2 {
def unapply(in:Int):Option [String] = {
println(Ex2)
if(in == 2)Some(2)else None
}
}
val pf:PartialFunction [Int,String] = {
case Ex1(result)=>结果
案例Ex2(结果)=>结果
}
val in = 2
if(pf.isDefinedAt(in))pf(in)
$ b
Ex1
Ex2
Ex1
Ex2
res52:Any = 2
最糟糕的情况,您的模式与上次匹配的地方,您在调用PartialFunction时已经评估过模式/提取器两次。如果匹配自定义提取器,而不仅仅是一个简单的类或列表模式匹配(例如,如果您有一个提取器来解析XML文档并返回一些值对象),则这可能变得效率低下。
PartialFunction#lift受到相同的双重评估:
scala> pf.lift(2)
是副作用的话)。
Ex1
Ex2
Ex1
Ex2
res55:Option [String] =一些(2)
$ c $如果没有可能调用所有提取器两次,有条件地调用函数吗?
解决方案您的问题的答案基本上是是,并且此行为(
PartialFunction
isDefinedAt
建议的新类型
FunctionWithDefault
没有isDefinedAt
并且有一个方法:trait FunctionWithDefault [-I,+ O] {
def applyOrElse [OO>:O](i:I,default :I => OO):OO
}
有点像
选项
sgetOrElse
方法。
我不得不说,像往常一样,我无法想象这种无效率会在绝大多数情况下带来任何表现问题。
This is something I've wondered about for a while. I see this pattern a lot:
if (pf.isDefinedAt(in)) pf(in)
By breaking this up into two separate calls, all of the patterns that were evaluated in #isDefinedAt are then also evaluated in #apply. For example:
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)
Which prints
Ex1 Ex2 Ex1 Ex2 res52: Any = 2
In the worst case, where your pattern matches last, you've evaluated your patterns/extractors twice when calling a PartialFunction. This could become inefficient when matching over custom extractors that did more than just a simple class or list pattern match (for example, if you had an extractor that parsed an XML document and returned some value objects)
PartialFunction#lift suffers from the same double-evaluation:
scala> pf.lift(2) Ex1 Ex2 Ex1 Ex2 res55: Option[String] = Some(2)
Is there a way to conditionally call a function if it is defined without potentially calling all of your extractors twice?
解决方案There is a conversation going on about this right now on the scala-internals mailing list. Martin Odersky has suggested a new type:
FunctionWithDefault
. Martin talks not only of a run-time penalty, but a compile time penalty (of class file bloat) of usingPartialFunction
:The answer to your question is essentially "yes" and and this behaviour (of
PartialFunction
) will not change either due to backwards-compatibility issues (for example, what if theisDefinedAt
is side-effecting).The new type being proposed,
FunctionWithDefault
has noisDefinedAt
and has a method:trait FunctionWithDefault[-I, +O] { def applyOrElse[OO >: O](i : I, default : I => OO) : OO }
which acts a bit like
Option
sgetOrElse
method.I have to say that, as usual, I cannot imagine this inefficiency poses any sort of performance problem in the overwhelming majority of cases.
这篇关于PartialFunction设计效率低下吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!