具有多个条件的 Scala 循环 - 返回什么?

Omn*_*ent 1 scala

我正在为不耐烦的人使用 Scala,并遇到了一个我似乎无法理解的多条件循环示例。

来自 Java 背景,我将这些循环视为嵌套的 for 循环。但是为什么第一个返回 acollection和第二个 a String?

scala> for (i <- 0 to 1; c <- "Hello") yield (i + c).toChar
res11: scala.collection.immutable.IndexedSeq[Char] = Vector(H, e, l, l, o, I, f, m, m, p)

scala> for (c <- "Hello"; i <- 0 to 1) yield (i + c).toChar
res12: String = HIeflmlmop
Run Code Online (Sandbox Code Playgroud)

Łuk*_*asz 5

因为理解只是语法糖并被翻译成对map, flatMap, 的调用withFilter(foreach如果你不使用 yield)。

for {
  i <- 0 to 1
  c <- "Hello"
} yield (i + c).toChar
Run Code Online (Sandbox Code Playgroud)

相当于

(0 to 1).flatMap(i => "Hello".map(c => (i + c).toChar))
Run Code Online (Sandbox Code Playgroud)

这些转换器的定义方式是,它们返回调用它们的相同类型的集合,或者最接近的集合,例如,这里最终Range变为 a Vector,因为您不能拥有Range包含任意字符的集合。从String你开始还可以有String回来。

一般来说,您可以这样想:for comprehension 创建的结果类型将与第一个生成器的类型相同(或最接近的)。

例如,如果您将字符串转换为 Set

for {
  c <- "Hello".toSet[Char]
  i <- 0 to 1
} yield (i + c).toChar
Run Code Online (Sandbox Code Playgroud)

你会得到一个Set回报,因为它是一个集合,它不会包含重复项,所以结果是不同的。Set(e, f, m, I, l, p, H, o)

确定类型的方式涉及CanBuildFrom特征。您可以在此处阅读有关其工作原理的更多信息