2011-06-25 99 views
6

在我继续努力学习scala的过程中,我正在通过Odersky的“Scala by Example”以及关于第一类函数的章节,匿名函数部分避免了递归匿名函数的情况。我有一个似乎可行的解决方案。我很好奇,如果有更好的答案。如何编写递归匿名函数?

从PDF: 代码展示高阶函数

def sum(f: Int => Int, a: Int, b: Int): Int = 
    if (a > b) 0 else f(a) + sum(f, a + 1, b) 

def id(x: Int): Int = x 
def square(x: Int): Int = x * x 
def powerOfTwo(x: Int): Int = if (x == 0) 1 else 2 * powerOfTwo(x-1) 

def sumInts(a: Int, b: Int): Int = sum(id, a, b) 
def sumSquares(a: Int, b: Int): Int = sum(square, a, b) 
def sumPowersOfTwo(a: Int, b: Int): Int = sum(powerOfTwo, a, b) 

scala> sumPowersOfTwo(2,3) 
res0: Int = 12 

从PDF: 代码展示匿名函数

def sum(f: Int => Int, a: Int, b: Int): Int = 
    if (a > b) 0 else f(a) + sum(f, a + 1, b) 

def sumInts(a: Int, b: Int): Int = sum((x: Int) => x, a, b) 
def sumSquares(a: Int, b: Int): Int = sum((x: Int) => x * x, a, b) 
// no sumPowersOfTwo 

我的代码:

def sumPowersOfTwo(a: Int, b: Int): Int = sum((x: Int) => { 
    def f(y:Int):Int = if (y==0) 1 else 2 * f(y-1); f(x) }, a, b) 

scala> sumPowersOfTwo(2,3) 
res0: Int = 12 
+0

你确定吗? 'echo“2^2 + 3^2”| bc -l' - >'13'。 – sarnold

+0

这是一个重复http://stackoverflow.com/questions/5337464/anonymous-recursive-function-in-scala – Suroot

+1

@sarnold两个权力之和 - 即'2^a + 2^a + 1 + ... 2^b-1 + 2^b'' 2^2 + 2^3 = 4 + 8 = 12' –

回答

13

对于什么是值得的...(标题和“真正的问题”不完全同意)

递归匿名功能的对象可以通过FunctionN,然后使用this(...)内部apply的延伸的“长手”被创建。

(new Function1[Int,Unit] { 
    def apply(x: Int) { 
    println("" + x) 
    if (x > 1) this(x - 1) 
    } 
})(10) 

但是,这种通常引入的不规则性使得该方法通常不够理想。最好只用一个“名”,并有一些描述性的,模块化的代码 - 不,下面就是这样;-)

val printingCounter: (Int) => Unit = (x: Int) => { 
    println("" + x) 
    if (x > 1) printingCounter(x - 1) 
} 
printingCounter(10) 

快乐编码一个很好的理由。

2

可以概括这种间接递归:

case class Rec[I, O](fn : (I => O, I) => O) extends (I => O) { 
    def apply(v : I) = fn(this, v) 
} 

现在和可以使用间接递归作为被写成:

val sum = Rec[Int, Int]((f, v) => if (v == 0) 0 else v + f(v - 1)) 

同样的解决方案可以被用来实现例如记忆化。