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?
See Question&Answers more detail:os