我想创建一个函数,该函数将返回一个是参数x上f的n倍的函数的n倍函数,即f(f(f ... f(x)...))。
这是我的代码:
def repeated(f: Int => Int, n: Int) = {
var tek: Int => Int = f
for (i <- 0 to n) {
tek = x => f(tek(x))
}
tek
}
我知道这不是在Scala中执行此操作的正确方法,我只想了解幕后发生的事情。
像
repeated(x => x + 1, 5)(1)
一样调用它会导致堆栈溢出。我在调试器中注意到的是,重复完成后,将执行for循环内的行。似乎是惰性启动,也许for循环的主体是按名称传递的lambda?
最佳答案
您的x => f(tek(x))
正在变量tek
的结尾。一旦内部for循环至少运行一次,您的tek
就会成为自引用的,因为tek = x => f(tek(x))
会自行调用,这会导致无限递归和StackOverflowError
。
如果要使用for
-loop进行操作,则可以引入局部不可变的辅助变量来中断递归:
def repeated(f: Int => Int, n: Int) = {
var tek: Int => Int = identity
for (i <- 1 to n) {
val g = tek
tek = x => f(g(x))
}
tek
}
请注意,您的代码中至少有两个
f
应用程序过多:n = 0
的身份开头0
迭代到n
,即(n + 1)
次。 一个更简单的解决方案是:
def repeated[A](f: A => A, n: Int): A => A = { (a0: A) =>
var res: A = a0
for (i <- 1 to n) {
res = f(res)
}
res
}
关于scala - 在Scala中将功能重复N次,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51294506/