【问题标题】:How to write function simulating while loop in Scala如何在Scala中编写模拟while循环的函数
【发布时间】:2012-10-31 03:52:48
【问题描述】:

如何编写模拟while循环的函数?它需要 2 个参数:执行条件和表达式。

我尝试了以下方法:

val whileLoop: (Boolean,Any)=>Unit = (condition:Boolean, expression:Any) => {
 expression
 if(condition) whileLoop(condition,expression)
 () }    

但它似乎不起作用,例如我有数组:

val arr = Array[Int](-2,5,-5,9,-3,10,3,4,1,2,0,-20)    

我还有变量 i:

var i = 0

我想打印 arr 的所有元素。我可以用以下代码做到这一点:

while(i<arr.length) { println(tab(i)); i+=1 }

我想使用我的 whileLoop 函数来做同样的事情。但我不能编写引用变量并修改它的函数。我可以使用只有一个元素的数组来传递它,例如

val nr = Array(0)

和功能:

val printArray: Array[Int]=>Unit = (n:Array[Int]) => {
 println(arr(n(0)))
 n(0)+=1
 ()
}

然后在我的 whileLoop 中使用:

whileLoop(nr(0)<arr.length, printArray)

使用上述代码后,我得到 StackOverflowError 并且 nr(0) 等于零。还有以下功能:

val printArray: Array[Int]=>Unit = (n:Array[Int]) => {
 println(arr(nr(0)))
 nr(0)+=1
 ()
}

给出相同的结果。

如何编写正确的函数 whileLoop 并使用它来打印所有 arr 元素?

提前感谢您的建议。

【问题讨论】:

    标签: function scala while-loop


    【解决方案1】:

    您的实现的主要问题是条件和表达式仅在您第一次调用whileLoop 时计算一次。在递归调用中,您只需传递一个值,而不是表达式。

    您可以通过使用名称参数来解决这个问题:

    def whileLoop(cond : =>Boolean, block : =>Unit) : Unit =
      if(cond) {
        block
        whileLoop(cond, block)
      }
    

    举个例子:

    scala> val a = Array(1, 2, 3)
    scala> var i = 0
    scala> whileLoop(i < a.length, { println(i); i += 1 })
    1
    2
    3
    

    请注意,变量ai 被正确引用。在内部,Scala 编译器为条件和表达式(块)构建了一个 函数,这些函数维护对其环境的引用。

    还要注意,为了获得更多的语法糖,您可以将whileLoop 定义为一个currified 函数:

    def whileLoop(cond : =>Boolean)(block : =>Unit) : Unit =
      if(cond) {
        block
        whileLoop(cond)(block)
      }
    

    这允许您像实际的 while 循环一样调用它:

    whileLoop(i < a.length) {
      println(a(i))
      i += 1
    }
    

    【讨论】:

      【解决方案2】:

      这是我想出的: 首先,你的函数需要这 4 个参数:

      - array which is yet to be processed
      - predicate that tells the function when to stop
      - function that takes the array to be processed and current state and produces a new state
      - and state that is being propagated through the recurion:
      

      我认为代码很容易解释:

      def whileFunc[A,B](over: Array[A], predicate: Array[A] => Boolean, apply: (Array[A],B) => B, state: B):B = {
         val doIterate = predicate(over)
         if(doIterate) whileFunc(over.tail, predicate, apply, apply(over,state)) else state
      }
      

      这可以做得更好,但我尽量保持简单。要计算数组中的所有元素,您可以这样称呼它:

      scala>     whileFunc(Array(1,2,3), (a:Array[Int]) => !a.isEmpty,(a:Array[Int],s: Int) => s + a.head, 0)
      res5: Int = 6
      

      打印每个元素:

      whileFunc[Int, Unit](Array(1,2,3), (a:Array[Int]) => !a.isEmpty,(a:Array[Int],s: Unit) => print(a.head), Unit)
      123
      

      顺便说一句,如果你对这类东西感兴趣,我建议你购买 Scala 中的函数式编程,有两章可以让你实现这样的函数。这很有趣。

      【讨论】:

      • 也谢谢,这是个有趣的选择。
      猜你喜欢
      • 2020-08-14
      • 2012-12-03
      • 2015-06-26
      • 2012-07-15
      • 1970-01-01
      • 2010-10-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多