我正在为不耐烦的人使用 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)
因为理解只是语法糖并被翻译成对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特征。您可以在此处阅读有关其工作原理的更多信息