你可以用你的函數在自定義提取:
def test(i: Int): Int = i - 1
object Test {
def unapply(i: Int): Option[Int] = Some(test(i))
}
scala> List(1, 10, 20) collectFirst { case Test(i) if i > 0 => i }
res0: Option[Int] = Some(9)
可以概括這個解決方案一個D構成的那種提取的一類:
case class Extract[T, U](f: T => U) {
def unapply(t: T): Option[U] = Some(f(t))
}
scala> val Test2 = Extract(test)
Test2: Extract[Int,Int] = Extract($$Lambda$1326/[email protected])
scala> List(1, 10, 20) collectFirst { case Test2(i) if i > 0 => i }
res1: Option[Int] = Some(9)
您也可以包裝成後衛的提取,以及:
case class ExtractWithGuard[T, U](f: T => U)(pred: U => Boolean) {
def unapply(t: T): Option[U] = {
val u = f(t)
if (pred(u)) Some(u)
else None
}
}
scala> val Test3 = ExtractWithGuard(test)(_ > 0)
Test3: ExtractWithGuard[Int,Int] = ExtractWithGuard($$Lambda$1327/[email protected])
scala> List(1, 10, 20) collectFirst { case Test3(i) => i }
res2: Option[Int] = Some(9)
爲什麼'.iterator'? –
@GabrielePetronella迭代器是懶惰的,因此,這種方式在第一次返回肯定結果之前,只會調用'test'多次。 如果沒有'.iterator','test'會在開始評估'.find'條件之前首先應用於列表的_all_元素。因此,如果列表中有1000個元素,並且'test'在第一個元素上返回正值,則不會有'.iterator'的10000個調用,但只有一個調用。 – Dima
非常感謝你們倆。這有很大幫助。下面的包裝是一個很好的模式,以及使我很難從下面選擇:-) – Sven