Scala for循环中的顺序是否会影响

时间:2016-05-24 08:22:24

标签: scala

我是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
}

我找不到原因

1 个答案:

答案 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了解更多信息。