我想创建一个函数,该函数将返回一个是参数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/

    10-12 13:31