1

List 状态的文档:

结果集合的类型由列表的静态类型引导。这有时可能会导致意想不到的结果。例如:

// lettersOf 将返回可能重复的字母的 Seq[Char],而不是 Set def lettersOf(words: Seq[String]) = words flatMap (word => word.toSet)

// lettersOf 将返回一个 Set[Char],而不是 Seq def lettersOf(words: Seq[String]) = words.toSet flatMap (word => word.toSeq)

我很难理解这一点。StringOps.toSet 返回一个字符集,因此第一个示例最终返回一个字符序列 - 很好。那讲得通。我不明白为什么在第二个示例中 Scala 构造了 Set 而不是 Seq。

“生成的集合由列表的静态类型引导”到底是什么意思?

4

1 回答 1

1

因为在 Set 类中定义了canBuildFrom方法。正如您在 ScalaDoc 的CanBuildFrom特征中所见,它具有以下类型参数CanBuildFrom[-From, -Elem, +To]

From - 请求创建构建器的基础集合的类型。
Elem - 要创建的集合的元素类型。
To - 要创建的集合的类型。

基本上当你在集合上调用你的 flatMap 函数时,它会隐式调用Set.canBuildFrom[Char]它返回一个Set[Char]

至于静态类型。当 Scala 试图在集合类型之间进行转换时,它使用这个CanBuildFrom特性,这取决于集合的静态类型。

更新了评论

如果我们将 -Xprint:typer 添加到 scala 命令中,我们可以看到 Scala 编译器在 typer 阶段之后如何解析 flatMap 方法中使用的隐式方法 Set.canBuildFrom[Char]

def lettersOf(words: Seq[String]): scala.collection.immutable.Set[Char] = words.toSet[String].flatMap[Char, scala.collection.immutable.Set[Char]](((word: String) => scala.this.Predef.augmentString(word).toSeq))(immutable.this.Set.canBuildFrom[Char])
于 2013-05-22T19:58:20.887 回答