你可以用你的函数在自定义提取:
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