簡介
對於for迴圈的每次迭代,yield都會生成一個將被記住的值。就像有一個你看不見的緩衝區,for迴圈的每一次迭代都會將另一個新的值新增到該緩衝區。
當for迴圈結束執行時,它將返回所有已賦值的集合。返回的集合的型別與迭代產生的型別相同,因此Map會生成Map,List將生成List,等等。
另外請注意,最初的集合沒有改變。for / yield構造根據您指定的演算法建立一個新的集合。
例子
基於上面的資訊,來看幾個例子:
scala> val a = Array(1, 2, 3, 4, 5)
a: Array[Int] = Array(1, 2, 3, 4, 5)
scala> for (e <- a) yield e
res5: Array[Int] = Array(1, 2, 3, 4, 5)
scala> for (e <- a) yield e * 2
res6: Array[Int] = Array(2, 4, 6, 8, 10)
scala> for (e <- a) yield e % 2
res7: Array[Int] = Array(1, 0, 1, 0, 1)
scala> val b = List(1, 2, 3, 4, 5)
b: List[Int] = List(1, 2, 3, 4, 5)
scala> for (e <- b) yield e
res8: List[Int] = List(1, 2, 3, 4, 5)
複製程式碼
正如你所見, 例子中被 yield 的是 Array[Int],返回的也是Array[Int];被 yield 的是 List[Int],返回的也是List[Int]。
那麼看看下面的例子:
scala> for (i <- 1 to 5) yield i
res10: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5)
scala> for (i <- 1 to 5) yield i * 2
res11: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10)
scala> for (i <- 1 to 5) yield i % 2
res12: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 0, 1, 0, 1)
複製程式碼
這兒yield的是一個range,但是產生的結果卻是vector。這是因為Range是一個特殊的資料結構,用於儲存等間隔的一列連續的陣列,在這個資料結構上呼叫map或者yield等後,不能保證結果一定還是一個等間隔的一列連續的陣列,那麼結果當然也不能再是Range型別了。
於是就有了之前提到的implicit轉化。
for迴圈, yield和guards
假如你熟悉了 Scala 複雜的語法, 你就會知道可以在 for 迴圈結構中加上 ‘if’ 表示式. 它們作為測試用,通常被認為是一個guards,你可以把它們與 yield 語法聯合起來用。
scala> val a = Array(1, 2, 3, 4, 5)
a: Array[Int] = Array(1, 2, 3, 4, 5)
scala> for (e <- a if e > 2) yield e
res1: Array[Int] = Array(3, 4, 5)```複製程式碼