简体   繁体   English

Scala 中的匿名递归函数

[英]Anonymous recursive function in Scala

Is there a way to write an anonymous function that is recursive in Scala?有没有办法编写一个在 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.您可以使用 Y 组合器。 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.如果你不想触及“惊人的数学”,你可以回到 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).除了这个线程中的许多好的反应之外,Scala 没有给我们提供尾调用可优化的定点组合器这一事实一直困扰着我,以至于我决定编写一个宏来翻译类似 Y 组合器的调用到一个普通的、惯用的递归调用(当然还有尾调用优化)。 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 .我已经将针对 Scala 2.11 的宏实现(稍作调整也应该适用于 2.10)放入这个 gist

With this macro, we can perform ordinary recursive tasks in anonymous manner without fearing stack overflow eg有了这个宏,我们可以以匿名的方式执行普通的递归任务,而不必担心堆栈溢出,例如

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. Scala 上的递归调用。 Let me take sum of N numbers example for recursion让我以 N 个数字的总和为例进行递归

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.您可以看到 sumIt 的类型为 Int,Int 作为输入和返回值。 The sumIt lambda function takes as argument which is an Integer and it does recursive call on sumIt. sumIt lambda 函数将一个整数作为参数,并对 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM