Я собирался просто прокомментировать ответ Тенши, но потом решил расширить его до альтернативного подхода. Обратите внимание, что если вы используете map
в строгом Traversable, то весь список будет отображен до того, как произойдет какое-либо обнаружение. Это означает, что вы закончите выполнять немного больше работы.
Вместо этого вы можете просто найти:
def findResult[A, B](t: Traversable[Function1[A, B]], value: A, p: B => Boolean) =
t find (fn => p(fn(value)))
Вместо этого будет возвращена функция , которая удовлетворяет предикату p
для value
. Если вам вместо этого нужен результат, вам нужно только применить функцию к значению снова (при условии, что функция является ссылочно прозрачной). Это, конечно, поэтому будет выполнять немного больше работы, но, вероятно, будет немного меньше дополнительной работы, чем техника Тенши. Обратите внимание, что техника, которую вы придумали самостоятельно, выполняет нет дополнительную работу.
[обновление] Если вы действительно не хотите выполнять любую дополнительную работу, то вам следует использовать представление коллекции . Я должен был найти это, но я думаю, что у меня есть справка об этом. Теперь, прямо украдя код Тенши и добавив .view
, вот несколько копипаст из моей интерактивной сессии:
def f1(x: Int): Int = { println("f1"); x }
f1: (x: Int)Int
def f2(x: Int): Int = { println("f2"); x+1 }
f2: (x: Int)Int
def f3(x: Int): Int = { println("f3"); x+2 }
f3: (x: Int)Int
val fs = List(f1 _, f2 _, f3 _)
fs: List[(Int) => Int] = List(, , )
(fs.view map (f => f(1))) find (_ == 2)
f1
f2
res8: Option[Int] = Some(2)
Как видите, f1 и f2 выполнены, но не f3. Это связано с тем, что как только результат f2(1)
оказался равным == 2
, функция find
смогла остановиться. Это часть волшебства взглядов: ленивое отображение. Фактически, операции map
и find
слиты воедино благодаря представлениям! Или так мне сказали.
def findResult[A, B](t: Traversable[Function1[A, B]], value: A, p: B => Boolean) =
t.view map (f => f(value)) find p
def even(x: Int) = x % 2 == 0
findResult(fs, 1, even)
f1
f2
res13: Option[Int] = Some(2)
Итак, вот оно. Один из камней, который я нашел в документации, на которую я ссылался выше, был такой:
[По состоянию на Scala 2.8] Все коллекции, кроме потоков и представлений, являются строгими. Единственный способ перейти от строгой к ленивой коллекции - это метод view
. Единственный способ вернуться назад - через force
.