Hug*_*len 16 recursion language-features function-literal anonymous-function letrec
现在似乎有不少主流语言支持函数文字.它们也被称为匿名函数,但我不在乎它们是否有名称.重要的是函数文字是一个表达式,它产生一个尚未在别处定义的函数,因此例如在C中,&printf
不计算.
编辑添加:如果你有一个真正的函数文字表达式<exp>
,你应该能够将它传递给一个函数f(<exp>)
或立即将它应用于一个参数,即.<exp>(5)
.
我很好奇哪些语言可以让你编写递归的函数文字.维基百科的" 匿名递归 "文章没有给出任何编程示例.
我们以递归因子函数为例.
以下是我所知道的:
JavaScript/ECMAScript可以用callee
:
function(n){if (n<2) {return 1;} else {return n * arguments.callee(n-1);}}
Run Code Online (Sandbox Code Playgroud)在语言方面很容易letrec
,例如Haskell(称之为let
):
let fac x = if x<2 then 1 else fac (x-1) * x in fac
Lisp和Scheme中有等价物.请注意,绑定fac
是表达式的局部,因此整个表达式实际上是一个匿名函数.
还有其他人吗?
Joh*_*kin 16
大多数语言通过使用Y组合器来支持它.这是Python中的一个例子(来自cookbook):
# Define Y combinator...come on Gudio, put it in functools!
Y = lambda g: (lambda f: g(lambda arg: f(f)(arg))) (lambda f: g(lambda arg: f(f)(arg)))
# Define anonymous recursive factorial function
fac = Y(lambda f: lambda n: (1 if n<2 else n*f(n-1)))
assert fac(7) == 5040
Run Code Online (Sandbox Code Playgroud)
C#
阅读Wes Dyer的博客,你会发现@Jon Skeet的答案并不完全正确.我不是语言的天才,但是递归匿名函数和" fib函数真的只是调用本地变量fib引用的委托 "引用博客之间存在差异.
实际的C#答案看起来像这样:
delegate Func<A, R> Recursive<A, R>(Recursive<A, R> r);
static Func<A, R> Y<A, R>(Func<Func<A, R>, Func<A, R>> f)
{
Recursive<A, R> rec = r => a => f(r(r))(a);
return rec(rec);
}
static void Main(string[] args)
{
Func<int,int> fib = Y<int,int>(f => n => n > 1 ? f(n - 1) + f(n - 2) : n);
Func<int, int> fact = Y<int, int>(f => n => n > 1 ? n * f(n - 1) : 1);
Console.WriteLine(fib(6)); // displays 8
Console.WriteLine(fact(6));
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
你可以在Perl中做到这一点:
my $factorial = do {
my $fac;
$fac = sub {
my $n = shift;
if ($n < 2) { 1 } else { $n * $fac->($n-1) }
};
};
print $factorial->(4);
Run Code Online (Sandbox Code Playgroud)
该do
块不是绝对必要的; 我把它包括在内以强调结果是一个真正的匿名函数.