2010-03-18 15 views
6

Dies ist etwas, auf das ich häufig stoße, aber ich kenne die elegante Art nicht. Ich habe eine Sammlung von Foo-Objekten. Foo verfügt über eine Methodenleiste(), die ein Null- oder ein Bar-Objekt zurückgeben kann. Ich möchte die Sammlung scannen, die bar() -Methode jedes Objekts aufrufen und beim ersten Objekt anhalten, das eine tatsächliche Referenz zurückgibt und diese Referenz vom Scan zurückgibt.best scala idiom für find & return

Offensichtlich:

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

funktioniert der Trick, sondern ruft #bar zweimal.

Antwort

7

Sie es iterator mit jedem Iterable unter Verwendung tun können (was faul wertet - es heißt elements in 2.7). Probieren Sie es aus:

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) 
+0

Gibt es einen Unterschied zwischen dieser und einer Projektion? – IttayD

+0

Memoisierung von Stream [T] ist der Unterschied 'val mapped = foos.elements.map (_. Bar); mapped.find (_! = null); mapped.find (_! = null) 'gibt' Some (bar say 4) 'und' None' zurück mit 'val mapped = foos.projection.map (_. bar); mapped.find (_! = null); mapped.find (_! = null) 'gibt zweimal' Some (bar say 4) 'zurück. –

+0

'foos.view' in Scala 2.8 gibt das selbe wie' foos.projection' zurück, wertet aber die Elemente zweimal aus (keine Memoisierung). –

8

Arbeiten an dem Bach [T] zurück von Seq.projection ist ein schöner Trick

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

Damit werden die Werte der Karte benötigt Fund auszuführen.

In Scala 2.8 es ist:

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