2016-06-21 7 views
1

Ich gehe durch scala für die ungeduldigen und stieß auf ein Beispiel der Multi-Condition-Loops, die ich nicht zu verstehen scheinen.Scala Schleifen mit mehreren Bedingungen - was wird zurückgegeben?

Ausgehend von Java-Hintergrund sehe ich diese Schleifen als geschachtelte für Schleifen. Aber warum gibt die erste eine collection und eine zweite String?

scala> for (i <- 0 to 1; c <- "Hello") yield (i + c).toChar 
res11: scala.collection.immutable.IndexedSeq[Char] = Vector(H, e, l, l, o, I, f, m, m, p) 

scala> for (c <- "Hello"; i <- 0 to 1) yield (i + c).toChar 
res12: String = HIeflmlmop 
+0

Siehe http://docs.scala-lang.org/tutorials/FAQ/yield.html –

+0

Kurz gesagt, mit For-Comprehensions der Rückgabetyp wird durch die erste Sammlung bestimmt (oder verfahrbar) verwendet. –

Antwort

4

für Comprehensions sind nur Syntax Zucker und sind übersetzt in Aufrufe von map, flatMap, withFilter (auch foreach, wenn Sie keine Ausbeute verwenden).

for { 
    i <- 0 to 1 
    c <- "Hello" 
} yield (i + c).toChar 

entspricht

(0 to 1).flatMap(i => "Hello".map(c => (i + c).toChar)) 

Diese Transformatoren in einer Art und Weise definiert sind, dass sie die gleiche Art von Sammlung Rückkehr wurden sie aufgefordert, oder in der Nähe ein, zum Beispiel hier Range ein Vector werden in das Ende, wie Sie Range nicht haben können, das beliebige Zeichen enthält. Ab String können Sie immer noch String zurück haben.

Im Allgemeinen kann man sich das folgendermaßen vorstellen: Der Ergebnistyp, der für das Verständnis erstellt wird, ist derselbe wie der Typ des ersten Generators (oder möglichst ähnlich).

Zum Beispiel, wenn Sie Zeichenfolge in eine Set

for { 
    c <- "Hello".toSet[Char] 
    i <- 0 to 1 
} yield (i + c).toChar 

konvertieren Sie eine Set zurück zu bekommen, und weil es ein Satz ist, wird es keine Duplikate enthalten, so das Ergebnis ist anders. Set(e, f, m, I, l, p, H, o)

Die Art und Weise, wie der Typ bestimmt wird, umfasst das Merkmal CanBuildFrom. Sie können mehr darüber lesen, wie es funktioniert here

+0

Eine andere Möglichkeit, Ihr Beispiel mit 'Set' zu machen:' for {_ <- Set (''); c <- "Hallo"; i <- 0 bis 1} Ausbeute (i + c). toChar ". Nicht sicher, es ist ein besserer Weg, aber manchmal sieht es sauberer aus. –

1

Verwenden scala 2.11.8 repl für desugar (Tabulatortaste drücken, nach dem Druck, Entfernen <pressed TAB here>):

scala> for (i <- 0 to 1; c <- "Hello") yield (i + c).toChar //print<pressed TAB here> 

scala.Predef.intWrapper(0).to(1).flatMap[Char, scala.collection.immutable.IndexedSeq[Char]](((i: Int) => 
    scala.Predef.augmentString(scala.Predef.augmentString("Hello"). 
     map[Char, String](((c: Char) => i.+(c).toChar))(scala.Predef.StringCanBuildFrom))))(scala.collection.immutable.IndexedSeq.canBuildFrom[Char]) // : scala.collection.immutable.IndexedSeq[Char] 

scala> for (i <- 0 to 1; c <- "Hello") yield (i + c).toChar //print 
res4: scala.collection.immutable.IndexedSeq[Char] = Vector(H, e, l, l, o, I, f, m, m, p) 

scala> for (c <- "Hello"; i <- 0 to 1) yield (i + c).toChar //print<pressed TAB here> 

scala.Predef.augmentString("Hello").flatMap[Char, String](((c: Char) => scala.Predef.intWrapper(0).to(1). 
     map[Char, scala.collection.immutable.IndexedSeq[Char]](((i: Int) => i.+(c).toChar))(scala.collection.immutable.IndexedSeq.canBuildFrom[Char])))(scala.Predef.StringCanBuildFrom) // : String 

scala> for (c <- "Hello"; i <- 0 to 1) yield (i + c).toChar //print 
res5: String = HIeflmlmop 

lesbarer Ausgang:

scala> (0 to 1).flatMap(i => "Hello".map(c => (i+c).toChar)) 
res14: scala.collection.immutable.IndexedSeq[Char] = Vector(H, e, l, l, o, I, f, m, m, p) 

scala> "Hello".flatMap(c => (0 to 1).map(i => (i + c).toChar)) 
res15: String = HIeflmlmop 
Verwandte Themen