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