Anonymous recursive function in Scala
有没有办法在Scala中编写一个递归的匿名函数? 我在考虑这样的事情:
1 2 3 4 5
| ((t : Tree ) => {
print (t. value);
for (c <- t. children)
thisMethod (c )
})(root ) |
(相关问题:哪些语言支持*递归*函数文字/匿名函数?)
如您发布的链接中所述。你可以使用Y-combinator。这是一个例子:
1 2 3 4 5 6 7 8
| 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 |
请注意,它不适用于大数字。
小心尾调用优化。
-
原始意义上的"惊人"让我觉得自己迷失在迷宫中。 fix是一个函数,它接受一个函数,它本身接受一个参数并返回另一个接受一个参数的函数,然后它......好吧,我需要一个更好的解释...
-
但这不允许尾调用优化,我是否正确?
-
@Malvolio:fix是一个函数,它接受另一个函数f作为其参数,并返回该函数的一个固定点,即x的值x。计算其他函数的固定点的函数称为定点组合器。 Y组合器只是定点组合器的一个例子。定点组合器提供了一种描述语法中递归的方法,例如lambda演算,它不允许自引用定义。
-
请帮帮我:stackoverflow.com/questions/34775656/… @Rustem Suniev
如果你不想点击"惊人的数学",你可以回到scala的对象方面。
1 2 3
| val fact = new Function1 [Int,Int ]{
def apply (x :Int ):Int = if(x ==1) x else x * apply (x- 1)
} |
为了使它看起来更怪,你也可以使用这种代码风格:
1 2 3
| val fact = new ((Int ) => Int ){
def apply (x :Int ):Int = if(x ==1) x else x * apply (x- 1)
} |
-
这个看起来比简单new Function[Int, Int] {...}好多了。谢谢!
在这个线程中添加了许多好的响应,Scala没有给我们尾调用优化定点组合器这一事实一直困扰着我,所以我决定编写一个宏来翻译类似Y-combinator的调用一个普通的,惯用的递归调用(当然,尾部调用优化)。这个想法就像是一个电话
1
| fix[Int,Int]((next) => (y) => ...body...) |
很容易翻译成
1 2 3 4 5 6
| ({(input ) =>
object next {
def apply (y :Int ):Int = ... body...
}
next (input )
}) |
我已经将针对Scala 2.11的宏实现(稍微调整也应该与2.10一起使用)放到了这个要点中。
使用这个宏,我们可以匿名方式执行普通的递归任务,而不用担心堆栈溢出,例如
1 2
| import asia. blip. ymacro. YMacro. _
(y [BigInt,BigInt ]((xx ) => (y ) => if(y ==1) 1 else y * xx (y- 1)))(2000) |
给
1
| res0: BigInt = 33162750924506332411753933805763240382811... |
-
我想我仍然想知道你是否可以添加tailrec注释,以便它可以进行尾调用优化。
-
@JoshCason认为Scala很聪明,可以在我给出的例子中推断出tailrec。说实话,我不太确定更多涉及的用例。
一个非常简单的方法:
1 2 3 4 5 6 7 8 9 10 11 12
| 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) |
-
递归函数是f,这不是匿名的。它在匿名函数内定义的事实不会改变它。
-
downvote是没有根据的,因为解决方案符合问题所预期的目的。此外,你提出了这个解决方案,而上面有两个非常类似的解决方案,使用def apply而不是def f。
-
您的解决方案是否比def f向上移动一行更正确?因为如果没有说明我的观点,如果是,则解释为什么除了f的范围之外它们不完全相同