lambda and closure

lambda

lambda 表达式听说过吗?先给一段 C++ 代码:

1
2
3
4
5
6
7
8
9
10
11
12
auto sqr = [](int x){return x * x; };
cout << sqr(4) << endl;

auto sqr2 = [](int x) -> int {
return x * x;
};
cout << sqr2(5) << endl;

function<int (int)> fac = [&] (int a) -> int{
return a ? a * fac(a - 1) : 1;
};
cout << fac(5) << endl;

这段代码会输出 16、25 和 120 。可以看出, lambda 表达式就是一个匿名函数一样的东东吧。你完全可以把 lambda 函数当成普通函数一样用。

当然,普通的 lambda 不可以递归,但是如果你不用 auto (很残忍吧),还是可以实现递归的,就像上面的 fac 。至于鼎鼎大名的 Y 组合字 嘛,感觉很厉害的样子。

可以看到 sqr2sqr 是同一种函数,只是两个的写法不同罢了。我个人感觉 sqr2 好看些 = =,而且这种函数申明方式还可以直接申明全局函数呢。

closure

所谓 closure ,就是闭包。闭包就是建立 anonymous function 上的一个东西,就是记录的周围环境的 lambda 表达式。

比如说这么一段 C++ 代码:

1
2
3
4
5
6
7
auto gen = [](int a) -> function<int (int)> {
return [a](int b) -> int {
return a + b;
};
};
auto f = gen(3);
cerr << f(4) << endl;

仔细看 f 的定义,会发现 f 就是一个函数,这个函数接受一个参数 b ,返回构造时传入的参数 a + b 。那么在 f 中,已经不见了 a 的踪影,但是它又对 f 产生了影响。我们可以假设有这么个函数:

1
2
3
auto g = [](int a, int b) -> int {
return a + b;
}

但是我们想一部分一部分确定参数,也就是先确定 a 再确定 b 。为此 gen 函数就是接收一个参数 a ,返回一个函数 f ,而这个 f 中包含了 a 的信息。那么就可以说, f 就构成了一个 closure ,它包含了不在本地的信息。

unlambda

说起 lambda 表达式,就不得不让我想起这个奇葩的语言。

unlambda 中没有变量,只有两个函数。 k 作为一个普通的函数, s 貌似实现了 CurryingCurrying 后的 lambda 函数不就是 closure 嘛。好像有个专业名词叫做 SKI组合子演算 的样子。