如何在Scala中编写循环函数模拟

Pau*_*aul 15 scala function while-loop

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

我尝试了以下方法:

val whileLoop: (Boolean,Any)=>Unit = (condition:Boolean, expression:Any) => {
 expression
 if(condition) whileLoop(condition,expression)
 () }    
Run Code Online (Sandbox Code Playgroud)

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

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

我也有变量i:

var i = 0
Run Code Online (Sandbox Code Playgroud)

我想打印arr的所有元素.我可以使用以下代码执行此操作:

while(i<arr.length) { println(tab(i)); i+=1 }
Run Code Online (Sandbox Code Playgroud)

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

val nr = Array(0)
Run Code Online (Sandbox Code Playgroud)

和功能:

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

然后在我的whileLoop中使用:

whileLoop(nr(0)<arr.length, printArray)
Run Code Online (Sandbox Code Playgroud)

使用上面的代码后,我得到StackOverflowError,nr(0)等于零.还有以下功能:

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

给出相同的结果.

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

提前感谢您的建议.

Phi*_*ppe 28

您的实现的主要问题是,当您第一次调用时,条件和表达式仅被评估一次whileLoop.在递归调用中,您只传递一个值,而不是表达式.

您可以使用by-name参数解决此问题:

def whileLoop(cond : =>Boolean, block : =>Unit) : Unit =
  if(cond) {
    block
    whileLoop(cond, block)
  }
Run Code Online (Sandbox Code Playgroud)

举个例子:

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

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

还要注意,对于更多的语法糖whileLoop很棒,你可以定义为一个currified函数:

def whileLoop(cond : =>Boolean)(block : =>Unit) : Unit =
  if(cond) {
    block
    whileLoop(cond)(block)
  }
Run Code Online (Sandbox Code Playgroud)

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

whileLoop(i < a.length) {
  println(a(i))
  i += 1
}
Run Code Online (Sandbox Code Playgroud)