我在理解n Queens problem的Scala解决方案时遇到一些困难,下面是假设正确定义了isSafe的实现
def queens(n: Int): Set[List[Int]] = {
def placeQueens(k: Int): Set[List[Int]] = k match {
case 0 => Set(List())
case _ =>
for {
queens <- placeQueens(k - 1)
col <- 0 until n
if isSafe(col, queens )
}yield k :: queens
}
placeQueens(n)
}
正如我所见,理解上理解上应该返回一个缓冲集合,我在这里看到它缓存了k :: queens
的皇后列表,但它确实返回了Set[List]
的定义。有人可以说明这种for
理解是如何起作用的吗?
我的假设是正确的for
每次都会返回一个集合集合,因为在这种情况下我处理嵌套for表达式中的Seq和Set它返回Set[List]
。
这个问题与for
在实施nQueen而不是nQueen时的理解更为相关。
答案 0 :(得分:1)
请记住,for
理解,实质上,当应用于序列时,使用在for
- 主体内部指定的函数来描述该序列的元素的映射。因此,最终结果将是{{1}主体返回的类型的原始外部类型(即Set
,List
或任何其他Seq
- 后代)的集合。 } -comprehension。
在您的情况下,外部类型为for
,内部类型为Set
的类型(k :: queens
,因为List[Int]
是序列中的元素由queens
返回,placeQueens
,Set[List[Int]]
返回与k::queens
相同类型的序列。
答案 1 :(得分:1)
回想一下,for comprehension只是map,flatmap和filter的语法糖,你在这个例子中使用了所有三个。无论您在yield块中产生什么,都会添加到映射的集合中。您可能会发现this article on how yield works很有趣。
当您产生k :: queens
时,您正在创建一个列表,其中k添加到皇后列表中,该列表是使用k-1
从递归调用生成的。
你的假设是正确的。 for
理解将返回所涉及的列表类型。由于placeQueens返回Set[List[Int]]
,因此for comprehension。 for
理解的翻译是这样的:
placeQueens(k-1).flatMap { queens =>
(0 until n).withFilter { col =>
isSafe(col, queens)
}.map { col =>
k::queens
}
}