Anonymous recursive function in Scala
Is there a way to write an anonymous function that is recursive in Scala? I'm thinking of something like this:
开发者_如何转开发((t: Tree) => {
print(t.value);
for (c <- t.children)
thisMethod(c)
})(root)
(Related question: Which languages support *recursive* function literals / anonymous functions?)
As described in the link you posted. You can use Y-combinator. Here is example:
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
Note it doesn't work with big numbers. Be careful with tail call optimization.
If you don't want to hit the "Amazing mathematics" you could just revert to the object aspects of scala.
val fact = new Function1[Int,Int]{
def apply(x:Int):Int = if(x==1) x else x * apply(x-1)
}
in order to make it look geekier you can also use this code style:
val fact = new ((Int) => Int){
def apply(x:Int):Int = if(x==1) x else x * apply(x-1)
}
Adding to the many good responses here in this thread, the fact that Scala is not giving us tail call optimizable Fixed-point combinator has been bothering me so much so that I've decided to write a macro to translate Y-combinator-like call to an ordinary, idiomatic recursive call (with tail call optimization, of course). The idea is that a call like
fix[Int,Int]((next) => (y) => ...body...)
is readily translatable into
({(input) =>
object next {
def apply(y:Int):Int = ...body...
}
next(input)
})
I've put up macro implementation targeting Scala 2.11 (with minor tweak should also work with 2.10) into this gist.
With this macro, we can perform ordinary recursive tasks in anonymous manner without fearing stack overflow e.g.
import asia.blip.ymacro.YMacro._
(y[BigInt,BigInt]((xx) => (y) => if(y==1) 1 else y * xx(y-1)))(2000)
gives
res0: BigInt = 33162750924506332411753933805763240382811...
Recursive calls on Scala. Let me take sum of N numbers example for recursion
var sumIt:(Int => Int) = (x: Int) => {if(x<=1) 1 else sumIt(x-1)+x}
scala> sumIt(10)
val res141: Int = 55
You can see the sumIt has its type with Int, Int as Input and the return value. The sumIt lambda function takes as argument which is an Integer and it does recursive call on sumIt.
I just this example for easy understanding the recursion call. You can direct formula for this logic like...
sumValue = (N*(N+1)) /2
A very simple approach:
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)
精彩评论