【问题标题】:why yield can not work with while loop in scala为什么产量不能与scala中的while循环一起使用
【发布时间】:2015-01-21 07:16:16
【问题描述】:

在 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 上搜索过,但找不到答案。

【问题讨论】:

标签: scala yield-keyword


【解决方案1】:

这完全取决于转换为我们可以“屈服”的捕获状态的内容:

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

【讨论】:

    【解决方案2】:

    因为while 的工作方式与此处描述的类似:while-loop-expressions 即while循环表达式返回Unit

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

    【讨论】:

      【解决方案3】:

      区别在于for comprehension的解释,可以看成是DSL。 如果有 yield,则使用 ma​​pflatMap 将理解转换为某些内容并收集结果。 如果没有 yield 表达式将被转换为使用 foreach 的东西,迭代所有值而忽略结果。

      另一方面,

      虽然只是一个函数,它在满足特定条件之前执行某些操作并且不返回任何内容,即最后的 Unit。 它只是用于 sied 效果而不是用于返回结果。因此,即使您使用 yield,结果也会被丢弃。

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

      虽然返回 Unit,例如 foreach

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

      而带有 yieldfor 返回一个结果,其行为类似于 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)
      

      【讨论】:

        【解决方案4】:

        因为 while 循环是 java 等效的 while 循环,并且“for 循环”被转换为函数调用:&lt;IndexedSeq&gt;.map(如果您使用 yield)或&lt;IndexedSeq&gt;.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
                ()
            }
          }
        }
        

        【讨论】:

          猜你喜欢
          • 2021-05-20
          • 2014-01-09
          • 2018-09-08
          • 2022-12-12
          • 2016-08-29
          • 2014-12-20
          • 2015-11-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多