为什么 yield 不能在 Scala 中使用 while 循环



在Scala中,yield可以使用for循环;例如:

val ints: IndexedSeq[Int] = for(i <- 1 to 10) yield i

但我发现yield不能使用 while-loops,例如:

while (resultSet.next()) yield new Row(resultSet)

为什么 Scala 是这样设计的?

我在谷歌和stackoverflow上搜索过,但找不到答案。

因为 while 循环

是 java 等效的 while 循环,而 'for 循环' 被转换为函数调用:<IndexedSeq>.map(如果你使用 yield)或 <IndexedSeq>.foreach(如果你不在乎结果)。

示例 Scala 代码:

class ForVsWhileLoop {
  val dummy = for(i <- 1 to 10) yield i
  var dummy2 = Seq.empty[Int]
  var i = 0
  while(i <= 10)
    dummy2 :+= i
}

编译为 (scala -Xprint:parse ForVsWhileLoop.scala):

[[syntax trees at end of                    parser]] // ForVsWhileLoop.scala
package <empty> {
  class ForVsWhileLoop extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    // ***********************************************
    // the 'for loop' is translated to a function call
    val dummy = 1.to(10).map(((i) => i));

    var dummy2 = Seq.empty[Int];
    var i = 0;
    // *******************
    // classic while loop
    while$1(){
      if (i.$less$eq(10))
        {
          dummy2.$colon$plus$eq(i);
          while$1()
        }
      else
        ()
    }
  }
}

区别在于对理解的解释,可以看作是DSL。如果有收益,理解将使用mapflatMap转换为某些东西并收集结果。如果没有收益,表达式将使用foreach转换为内容,遍历所有值而忽略结果。

另一方面,它只是一个函数,它做某事直到满足某个条件并且不返回任何内容,即最后的 Unit。它只是为了获得 sied 效果而不是为了返回结果而调用。因此,即使您使用产量,结果也会被丢弃。

您上面给出的实现使用迭代器模式,并且与foreach完全相同。

虽然返回单位,如foreach

scala> val res : Unit = (1 to 10) foreach {i => i + 1}

对于 yield 返回结果并表现得像 map。

scala> val res : Seq[Int] = (1 to 10) map {i => i + 1}
res: Seq[Int] = Vector(2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
scala> val res = for (i<- 1 to 10) yield i +1 
res: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 3, 4, 5, 6, 7, 8, 9, 10, 11)

因为while的工作方式如下所述: while-loop-expression即 while 循环表达式返回 Unit .

您的yield值将隐式转换为此Unit如下所述:在 Scala 中隐式转换为单位类型。

这完全取决于什么被转换为我们可以"产生"的捕获状态:

https://docs.scala-lang.org/tutorials/FAQ/yield.html

相关内容

  • 没有找到相关文章

最新更新