лучшая идиома Scala для поиска и возврата

Я часто сталкиваюсь с этим, но не знаю, как это элегантно делать. У меня есть коллекция объектов Foo. Foo имеет метод bar (), который может возвращать null или объект Bar. Я хочу просканировать коллекцию, вызвать метод bar () каждого объекта и остановиться на первом, возвращающем фактическую ссылку, и вернуть эту ссылку из сканирования.

Очевидно:

foos.find (_. bar! = null) .bar

делает свое дело, но дважды вызывает #bar.


person IttayD    schedule 18.03.2010    source источник


Ответы (2)


Вы можете сделать это с любым Iterable, используя iterator (который вычисляет лениво - он называется elements в 2.7). Попробуйте это:

case class Foo(i: Int) {
  def bar = {
    println("Calling bar from Foo("+i+")")
    (if ((i%4)==0) "bar says "+i else null)
  }
}
val foos = List(Foo(1),Foo(2),Foo(3),Foo(4),Foo(5),Foo(6))
foos.iterator.map(_.bar).find(_!=null)
person Rex Kerr    schedule 18.03.2010
comment
есть ли разница между этим и использованием проекции? - person IttayD; 18.03.2010
comment
Мемоизация Stream [T] - это разница val mapped = foos.elements.map(_.bar); mapped.find(_!=null);mapped.find(_!=null) возвращает Some(bar say 4) и None, где val mapped = foos.projection.map(_.bar); mapped.find(_!=null);mapped.find(_!=null) возвращает дважды Some(bar say 4). - person Thomas Jung; 18.03.2010
comment
foos.view в Scala 2.8 возвращает то же самое, что и foos.projection, но оценивает элементы дважды (без мемоизации). - person Thomas Jung; 18.03.2010
comment
Используйте прогнозы, если вы хотите использовать результат несколько раз (или некоторые из небольшого набора методов, доступных только для прогнозов); в противном случае итераторы дешевле, поскольку они не заботятся о сохранении состояния. - person Rex Kerr; 18.03.2010

Работа над потоком [T], возвращенным Seq.projection - хороший трюк

foos.projection map (_.bar) find (_.size > 0)

Это отобразит значения, необходимые для выполнения find.

В Scala 2.8 это:

foos.view map (_.bar) find (_.size > 0)
person Thomas Jung    schedule 18.03.2010