哪些语言支持*递归*函数字面值/匿名函数?

27 浏览
0 Comments

哪些语言支持*递归*函数字面值/匿名函数?

现在看起来有相当多的主流编程语言支持函数字面量。它们也被称为匿名函数,但我不在乎它们是否有名字。重要的是,函数字面量是一个表达式,它生成一个在其他地方尚未定义的函数,所以例如在C中,`&printf`不算。
补充说明:如果你有一个真正的函数字面量表达式``,你应该能够将它传递给一个函数`f()`,或者立即将其应用于一个参数,即`(5)`。
我很好奇哪些语言允许你编写递归的函数字面量。维基百科的“匿名递归”文章中没有给出任何编程示例。
让我们以递归的阶乘函数作为例子。
以下是我知道的一些语言:

  • 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`的绑定是局部的,所以整个表达式实际上是一个匿名函数。

还有其他的吗?

0
0 Comments

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调用匿名函数。

0
0 Comments

从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组合子肯定可以解决问题,并且是一种更纯粹的递归方式 - 只是比我的“伪递归”解决方案更难理解 🙂

更难可能是一个低估的说法 🙂

0
0 Comments

大多数语言通过使用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的文章中。

0