如何编写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 元素?
提前感谢您的建议。
答案 0 :(得分:28)
实现的主要问题是,当您第一次调用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
请注意,正确引用了变量a
和i
。在内部,Scala编译器为条件和表达式(块)构建了函数,并且这些函数维护对其环境的引用。
另请注意,为了获得更多语法糖的精彩,您可以将whileLoop
定义为一个改进的函数:
def whileLoop(cond : =>Boolean)(block : =>Unit) : Unit =
if(cond) {
block
whileLoop(cond)(block)
}
这允许你像实际的while循环一样调用它:
whileLoop(i < a.length) {
println(a(i))
i += 1
}
答案 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中购买函数式编程,有两个章节可以让你实现这样的功能。这很有趣。