有没有办法在Scala中编写一个递归的匿名函数?我在考虑这样的事情:
((t: Tree) => {
print(t.value);
for (c <- t.children)
thisMethod(c)
})(root)
(相关问题:Which languages support *recursive* function literals / anonymous functions?)
答案 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)