Это то, о чем я задумывался некоторое время. Я вижу этот шаблон много:
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 # имеет такую же двойную оценку:
scala> pf.lift(2)
Ex1
Ex2
Ex1
Ex2
res55: Option[String] = Some(2)
Есть ли способ условно вызывать функцию, если она определена без потенциального вызова всех ваших экстракторов дважды?