Scala中的匿名recursion函数
有没有办法编写一个在Scala中recursion的匿名函数? 我在想这样的事情:
((t: Tree) => { print(t.value); for (c <- t.children) thisMethod(c) })(root)
(相关问题: 哪些语言支持*recursion*函数文字/匿名函数? )
正如您发布的链接所述。 你可以使用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
请注意,它不适用于大数字。 小心调用尾部优化。
如果你不想打“惊人的math”,你可以回到scala的对象方面。
val fact = new Function1[Int,Int]{ def apply(x:Int):Int = if(x==1) x else x * apply(x-1) }
为了使它看起来更加怪异,你也可以使用下面的代码风格:
val fact = new ((Int) => Int){ def apply(x:Int):Int = if(x==1) x else x * apply(x-1) }
在这个线程中join了许多好的回应,Scala并没有给我们提供可调优化的定点组合器这个事实一直困扰着我,所以我决定编写一个macros来翻译类似Y-combinator的调用到一个普通的,惯用的recursion调用(当然有tail调用优化)。 这个想法是,像一个电话
fix[Int,Int]((next) => (y) => ...body...)
很容易翻译成
({(input) => object next { def apply(y:Int):Int = ...body... } next(input) })
我已经把对Scala 2.11的macros观实现(小调整也应该与2.10一起工作)融入到这个要点中 。
有了这个macros,我们可以匿名的方式执行普通的recursion任务,而不用担心堆栈溢出
import asia.blip.ymacro.YMacro._ (y[BigInt,BigInt]((xx) => (y) => if(y==1) 1 else y * xx(y-1)))(2000)
给
res0: BigInt = 33162750924506332411753933805763240382811...
一个非常简单的方法:
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)