我是Scala的新手。我对foor循环中的顺序有疑问。
type Occurrences = List[(Char, Int)]
lazy val dictionaryByOccurrences: Map[Occurrences, List[Word]] = dictionary.groupBy(x => wordOccurrences(x))
def wordAnagrams(word: Word): List[Word] = dictionaryByOccurrences.getOrElse(wordOccurrences(word), List())
def combinations(occurrences: Occurrences): List[Occurrences] = occurrences match {
case List() => List(List())
case head::tail => {
for (o <- combinations(tail); x <- 1 to head._2)
yield (head._1, x) :: o
}
如果我改变for循环中的顺序,那就错了
def combinations(occurrences: Occurrences): List[Occurrences] = occurrences match {
case List() => List(List())
case head::tail => {
for (x <- 1 to head._2; o <- combinations(tail))
yield (head._1, x) :: o
}
我找不到原因
答案 0 :(得分:1)
for(x <- xs; y <- ys; ...) yield f(x, y, ...)
的类型构造函数默认与xs
相同。现在combinations
的返回类型是List[Occurrences]
,那么预期的类型构造函数是List[_]
,而1 to n
的类型构造函数是Seq[_]
。
以下代码有效:
def combinations(occurrences: Occurrences): List[Occurrences] = occurrences match {
case List() => List(List())
case head::tail => {
for (x <- (1 to head._2).toList; o <- combinations(tail))
yield (head._1, x) :: o
}
这也可行:
import collection.breakOut
def combinations(occurrences: Occurrences): List[Occurrences] = occurrences match {
case List() => List(List())
case head::tail => {
(for (x <- 1 to head._2; o <- combinations(tail))
yield (head._1, x) :: o)(breakOut)
}
}
深入地说,for(x <- xs; y <- ys; ...) yield f(...)
相当于xs.flatMap(...)
,List#flatMap
的完整签名如下:
def flatMap[B, That](f: (A) ⇒ GenTraversableOnce[B])
(implicit bf: CanBuildFrom[List[A], B, That]): That
您可以看到flatMap
的返回类型是魔术 That
,默认情况下为List[B]
,您可以查看Scala 2.8 CanBuildFrom了解更多信息。