Scala中的匿名递归函数

时间:2011-03-17 09:56:34

标签: scala recursion anonymous-function

有没有办法在Scala中编写一个递归的匿名函数?我在考虑这样的事情:

((t: Tree) => {
    print(t.value);
    for (c <- t.children)
        thisMethod(c)
})(root)

(相关问题:Which languages support *recursive* function literals / anonymous functions?

6 个答案:

答案 0 :(得分:49)

如您发布的链接中所述。你可以使用Y-combinator。这是一个例子:

scala> def fix[A,B](f: (A=>B)=>(A=>B)): A=>B = f(fix(f))(_)
fix: [A,B](f: ((A) => B) => (A) => B)(A) => B

scala> val fact = fix[Int,Int](f => a => if(a<=0) 1 else f(a-1) * a)
fact: (Int) => Int = <function1>

scala> fact(12)
res0: Int = 479001600

注意它不适用于大数字。 小心尾部调用优化。

答案 1 :(得分:23)

如果你不想点击“惊人的数学”,你可以回到scala的对象方面。

val fact = new Function1[Int,Int]{
    def apply(x:Int):Int = if(x==1) x else x * apply(x-1)
}

答案 2 :(得分:12)

为了让它看起来更漂亮,你也可以使用这种代码风格:

val fact = new ((Int) => Int){
  def apply(x:Int):Int = if(x==1) x else x * apply(x-1)
}

答案 3 :(得分:5)

在这个帖子中添加了许多好的响应,Scala没有给我们尾调用优化定点组合器这一事实一直困扰着我,所以我决定编写一个宏来翻译Y. -combinator-like调用普通的,惯用的递归调用(当然还有尾调用优化)。这个想法是像

这样的召唤
fix[Int,Int]((next) => (y) => ...body...)

很容易翻译成

({(input) =>
  object next {
    def apply(y:Int):Int = ...body...
  }
  next(input)
})

我已经将针对Scala 2.11的宏实现(稍微调整也应该与2.10一起使用)放到this gist中。

使用这个宏,我们可以匿名方式执行普通的递归任务,而不用担心堆栈溢出,例如。

import asia.blip.ymacro.YMacro._
(y[BigInt,BigInt]((xx) => (y) => if(y==1) 1 else y * xx(y-1)))(2000)

给出

res0: BigInt = 33162750924506332411753933805763240382811...

答案 4 :(得分:0)

Scala上的递归调用。 让我以N个数字为例进行递归

var sumIt:(Int => Int) = (x: Int) => {if(x<=1) 1 else sumIt(x-1)+x}


 scala> sumIt(10) 
val res141: Int = 55

您可以看到sumIt具有其类型,其中Int,Int作为输入和返回值。 sumIt lambda函数以Integer作为参数,并且对sumIt进行递归调用。

我只是这个示例,以方便理解递归调用。您可以直接为这种逻辑指定公式,例如...

sumValue = (N*(N+1)) /2

答案 5 :(得分:-1)

一种非常简单的方法:

val fact = { (x: Int) =>
  def f(x: Int): Int = if (x == 0) 1 else x * f(x-1)
  f(x)
}

// Use as anonymous function below
(1 to 5).map { (x: Int) =>
  def f(x: Int): Int = if (x == 0) 1 else x * f(x-1)
  f(x)
}

// res0: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 6, 24, 120)