2016-06-21 62 views
1

我正在經歷scala的不耐煩,並遇到了我似乎無法理解的多條件循環的例子。具有多個條件的Scala循環 - 返回什麼?

來自Java背景我正在將這些循環看作嵌套for循環。但爲什麼第一個返回collection和第二個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

請參閱http://docs.scala-lang.org/tutorials/FAQ/yield.html –

+0

簡而言之,在for-comprehensions中,返回類型由第一個集合或可穿越)使用。 –

回答

4

用於推導只是語法糖和被翻譯成調用map,flatMap,withFilter(如果不使用收益,也是foreach)。

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

相當於

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

這些變壓器的方式,他們回到同一類型的集合,他們被稱爲上,或最接近的一個定義,例如這裏Range成爲一個Vector結束,因爲你不能有Range包含任意字符。從String開始,您仍然可以使用String

一般而言,您可以這樣想:理解創建的結果類型與第一個生成器的類型(或最接近的可能)相同。

例如,如果你把字符串轉換成Set

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

你會得到一個Set回來,因爲它是一個集它將不包含重複這樣的結果是不同的。 Set(e, f, m, I, l, p, H, o)

類型的確定方式涉及CanBuildFrom特徵。你可以閱讀更多關於它是如何工作的here

+0

另一種方法來做你的例子'Set':'{_ < - Set(''); c < - 「你好」; i < - 0到1}產生(i + c).toChar'。不知道這是更好的方式,但有時它看起來更乾淨。 –

1

使用階2.11.8 REPL爲desugar(印刷後壓片,取出<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 

更可讀的輸出:

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