Это то, что я задумался некоторое время. Я часто вижу этот шаблон:
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)
Есть ли способ условно вызвать функцию, если она определена без потенциального вызова всех ваших экстракторов дважды?