哪些语言支持*递归*函数字面值/匿名函数?
哪些语言支持*递归*函数字面值/匿名函数?
现在看起来有相当多的主流编程语言支持函数字面量。它们也被称为匿名函数,但我不在乎它们是否有名字。重要的是,函数字面量是一个表达式,它生成一个在其他地方尚未定义的函数,所以例如在C中,`&printf`不算。
补充说明:如果你有一个真正的函数字面量表达式`
我很好奇哪些语言允许你编写递归的函数字面量。维基百科的“匿名递归”文章中没有给出任何编程示例。
让我们以递归的阶乘函数作为例子。
以下是我知道的一些语言:
- JavaScript / ECMAScript可以使用`callee`实现递归:
function(n){if (n<2) {return 1;} else {return n * arguments.callee(n-1);}}
- 在具有`letrec`的语言中很容易,例如Haskell(它称之为`let`):
let fac x = if x<2 then 1 else fac (x-1) * x in fac
并且在Lisp和Scheme中也有类似的方法。注意,`fac`的绑定是局部的,所以整个表达式实际上是一个匿名函数。
还有其他的吗?
Perl语言支持递归函数字面量/匿名函数。
原因:
- Perl语言中,匿名函数可以通过sub
关键字来定义,可以直接在函数内部调用自身,实现递归功能。
- 在给定的示例代码中,使用了嵌套匿名函数的方式来定义阶乘函数$fac
,并通过$fac
调用自身实现递归。
解决方法:
- 在Perl语言中,可以使用sub
关键字定义匿名函数,通过sub
关键字内部调用匿名函数自身实现递归功能。
- 示例代码中通过my $factorial = do { ... }
的方式将匿名函数赋值给$factorial
变量,然后通过$factorial
调用匿名函数。
整理成的文章如下:
Perl语言支持递归函数字面量/匿名函数。
原因:
- Perl语言中,匿名函数可以通过sub
关键字来定义,可以直接在函数内部调用自身,实现递归功能。
- 在给定的示例代码中,使用了嵌套匿名函数的方式来定义阶乘函数$fac
,并通过$fac
调用自身实现递归。
解决方法:
- 在Perl语言中,可以使用sub
关键字定义匿名函数,通过sub
关键字内部调用匿名函数自身实现递归功能。
- 示例代码中通过my $factorial = do { ... }
的方式将匿名函数赋值给$factorial
变量,然后通过$factorial
调用匿名函数。
从Wes Dyer的博客中可以看出,Skeet的回答并不完全正确。虽然我对语言不是很了解,但是递归匿名函数和“fib函数只是调用了局部变量fib引用的委托”是有区别的,引自博客的说法。
实际上,C#的答案可能是这样的:
delegate Func Recursive(Recursive r); static Func Y(Func, Func> f) { Recursive rec = r => a => f(r(r))(a); return rec(rec); } static void Main(string[] args) { Func fib = Y (f => n => n > 1 ? f(n - 1) + f(n - 2) : n); Func fact = Y (f => n => n > 1 ? n * f(n - 1) : 1); Console.WriteLine(fib(6)); // displays 8 Console.WriteLine(fact(6)); Console.ReadLine(); }
是的,Y组合子肯定可以解决问题,并且是一种更纯粹的递归方式 - 只是比我的“伪递归”解决方案更难理解 🙂
更难可能是一个低估的说法 🙂
大多数语言通过使用Y组合子来支持递归函数字面量/匿名函数。以下是Python中的一个例子(来自cookbook):
# 定义Y组合子 Y = lambda g: (lambda f: g(lambda arg: f(f)(arg))) (lambda f: g(lambda arg: f(f)(arg))) # 定义匿名递归阶乘函数 fac = Y(lambda f: lambda n: (1 if n<2 else n*f(n-1))) assert fac(7) == 5040
“大多数语言”不,任何静态类型语言都不能编写真正的Y组合子。
与您的说法相反,这是Scala中Y组合子的实现:scala-blogs.org/2008/09/y-combinator-in-scala.html
我认为这不是一个“真正的”Y组合子,因为Y组合子是一个非常特定形式的表达式,而该示例需要外部类型,并且涉及在表达式内部创建该类型的对象,这不符合Y组合子的定义。
这是一个有趣的论点,我对Y组合子的了解还不够充分。您所说的似乎与第二段开头的“一个众所周知的不动点组合子…”的几个句子的方向相同,该句子出现在en.wikipedia.org/wiki/Fixed_point_combinator的文章中。