2013-11-27 70 views
1

以下for-expression對我來說似乎很直觀。取List(1)中的每個項目,然後映射到List("a"),然後返回List[(Int, String)]for-expression to flatMap轉換

scala> val x = for { 
    | a <- List(1) 
    | b <- List("a") 
    | } yield (a,b) 
x: List[(Int, String)] = List((1,a)) 

現在,將其轉換爲flatMap,這似乎不太清楚。如果我理解正確,我需要先調用flatMap,因爲我在初始化List(1),然後應用從A => List[B]轉換的函數。

scala> List(1).flatMap(a => List("a").map(b => (a,b))) 
res0: List[(Int, String)] = List((1,a)) 

使用flatMap後,因爲我需要從A => B去似乎有必要使用map

但是,隨着項目的數量在for-expression(比如2至3項)增加了,我怎麼知道是否使用從for-expression轉換爲flatMapmapflatMap

+0

[獲取Scala的desugared部分for/comprehension表達式?](http://stackoverflow.com/questions/9891407/getting-the-desugared-part-of-a-scala-for-comprehension - 表達) – drexin

回答

8

在使用for理解你總是flatMap,直到你提取的最後一個值是你的map。所以,如果你有三個項目:

for { 
    a <- List("a") 
    b <- List("b") 
    c <- List("c") 
    } yield (a, b, c) 

這將是一樣的:

List("a").flatMap(a => List("b").flatMap(b => List("c").map(c => (a, b, c)))) 

如果你看看flatMap簽名是A => M[B]。因此,當我們添加元素到理解中時,我們需要flatMap,因爲我們繼續添加M[B]來理解。當我們到達最後一個元素時,沒有什麼可以添加的,所以我們使用map,因爲我們只是想從A => B去。希望這是有道理的,如果不是,你應該看看Coursera上的Reactive Programming類的一些視頻,因爲他們經歷了這一點。

+4

另請參見[Daniel Sobral的答案](http://stackoverflow.com/questions/1052476/what-is-scalas-yield/1059501#1059501),這也可以在Odersky書中找到,在規範中。 –