让我举一个例子来弄清楚问题出在哪里。比方说,你有:
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