为什么yield无法在scala中使用while循环

时间:2014-11-23 14:53:44

标签: scala yield-keyword

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

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

但我发现yield无法使用while循环,例如像:

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

为什么Scala设计得像这样?

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

4 个答案:

答案 0 :(得分:6)

因为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
        ()
    }
  }
}

答案 1 :(得分:3)

区别在于对理解的解释,可以看作是DSL。 如果有产量,则理解将使用地图 flatMap 转换为某些内容并收集结果。 如果没有产量,则表达式将使用 foreach 转换为某些内容,迭代忽略结果的所有值。

另一方面,只是一个功能,它会在满足某个条件之前执行某些操作并且不返回任何内容,即最后返回 Unit 。 它只是被称为sied效果而不是返回结果。因此,即使您使用 yield ,结果也会被丢弃。

您在上面给出的实现使用了Iterator模式,其工作方式与 foreach 完全相同。

虽然返回单位,例如 foreach

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

yield 会返回结果并且行为类似于地图。

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)

答案 2 :(得分:1)

因为while的工作原理如下所述:while-loop-expressions 即while循环表达式返回Unit

您的yield值会隐式转换为此Unit,如下所述:Implicit conversion to the Unit type in Scala

答案 3 :(得分:0)

这一切都取决于将什么转换为可以“屈服”的捕获状态:

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