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

时间:2016-06-21 12:12:46

标签: scala

我经历了scala的不耐烦,并且遇到了一个我似乎无法理解的多条件循环的例子。

来自Java背景我将这些循环视为嵌套for循环。但为什么第一个返回collection而第二个返回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

2 个答案:

答案 0 :(得分:4)

对于理解只是语法糖,并被转换为mapflatMapwithFilter(如果你不使用yield)的foreach的调用。

for {
  i <- 0 to 1
  c <- "Hello"
} yield (i + c).toChar

相当于

(0 to 1).flatMap(i => "Hello".map(c => (i + c).toChar))

这些变换器的定义方式是它们返回调用它们的相同类型的集合,或者最接近的集合,例如此处Range最终变为Vector并且## 39; t Range包含任意字符。从String开始,您仍然可以String返回。

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

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

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

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

确定类型的方式涉及CanBuildFrom特征。您可以详细了解其工作原理here

答案 1 :(得分:1)

对desugar使用scala 2.11.8 repl(打印后按Tab键,删除<pressed TAB here>):

scala> for (i <- 0 to 1; c <- "Hello") yield (i + c).toChar //print<pressed TAB here>

scala.Predef.intWrapper(0).to(1).flatMap[Char, scala.collection.immutable.IndexedSeq[Char]](((i: Int) => 
    scala.Predef.augmentString(scala.Predef.augmentString("Hello").
        map[Char, String](((c: Char) => i.+(c).toChar))(scala.Predef.StringCanBuildFrom))))(scala.collection.immutable.IndexedSeq.canBuildFrom[Char]) // : scala.collection.immutable.IndexedSeq[Char]

scala> for (i <- 0 to 1; c <- "Hello") yield (i + c).toChar //print
res4: 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 //print<pressed TAB here>

scala.Predef.augmentString("Hello").flatMap[Char, String](((c: Char) => scala.Predef.intWrapper(0).to(1).
        map[Char, scala.collection.immutable.IndexedSeq[Char]](((i: Int) => i.+(c).toChar))(scala.collection.immutable.IndexedSeq.canBuildFrom[Char])))(scala.Predef.StringCanBuildFrom) // : String

scala> for (c <- "Hello"; i <- 0 to 1) yield (i + c).toChar //print
res5: String = HIeflmlmop

更易读的输出:

scala> (0 to 1).flatMap(i => "Hello".map(c => (i+c).toChar))
res14: scala.collection.immutable.IndexedSeq[Char] = Vector(H, e, l, l, o, I, f, m, m, p)

scala> "Hello".flatMap(c => (0 to 1).map(i => (i + c).toChar))
res15: String = HIeflmlmop