讓我舉一個例子來弄清楚問題出在哪裏。比方說,你有:
val superSorts = Set('x)
val relations = Map('x -> Set('a, 'b))
此代碼:
val superSuperSorts =
for(
ss <- superSorts;
sss <- relations.get(ss); //get Option[Set[Sort]] and flatten the option
s <- sss //extract the elements from the Set
) yield s
翻譯爲:
superSorts.flatMap(
ss => relations.get(ss).flatMap(
sss => sss.map(
s => s)))
首先,請注意,最後一項是map
,而不是一個flatMap
。現在,讓我們考慮用以上數據進行迭代:
ss = 'x
sss = Set('a, 'b)
s = 'a, 'b
現在讓我們在代碼中向後走。
// Set('a, 'b) => Set('a, 'b)
sss.map(s => s)
// Some(Set('a, 'b)) => Some('a, 'b)????
relations.get(ss).flatMap(...)
看到問題在這裏? Option[Set[Sort]]
如何平展?有沒有這樣的事情作爲Some('a, 'b)
。
那麼,爲什麼原始代碼工作?
val superSuperSorts = superSorts.flatMap(relations.get(_)).flatMap(x=>x)
如果我們把它分解:
// Set('x) => Set(Set('a, 'b))
superSorts.flatMap(relations.get(_))
// Set(Set('a, 'b')) => Set('a, 'b)
(...).flatMap(x=>x)
就能查看所有的flatMap
被應用在Set
,不是Option
? Option
被flatMap
淘汰,從未發揮過作用。
的更多或更少的等價物,理解您的代碼將是:
val superSuperSorts = for {
x <- (for {
ss <- superSorts
sss <- relations.get(ss)
} yield sss)
s <- x
} yield s
這引入了幾個身份地圖:map(sss => sss)
和map(s => s)
,該回避的事實得到,在一個最後的發電機理解總是一個map
。
我想我可以使用for-comprehension來壓扁Option。 – ziggystar
它確實檢查了這個代碼:val m = Map(1 - >「a」,2 - >「b」)。 for(lx < - List(1,3); a <-m.get(lx))產生a。觀察返回類型! – AndreasScheinert
我更新了我的答案。也許現在更清楚了。 – sschaef