what's closure in PL? 🔗
在函数式编程语言中,宣传函数是一等公民,把函数作为一种类型定义对象,把函数作为函数的参数和返回值时。那么我们定义一个函数时,很自然出来一个问题:函数可以使用哪些变量?
- 函数自己的实参
- 函数内定义的局部变量
- 程序整个生命周期内都一直存活的全局静态变量
- Outer函数A定义Inner函数B,并把Inner函数B作为Outer函数A的返回值, Inner函数B中能使用scope A中的变量吗?
- 当然可以,站在Inner函数B的角度下,Inner函数B出生在Outer函数A里面(出生==首次被定义),自然看到函数A的内部变量了。
- Outer函数A对应的scope(作用域)下有的东西可以被Inner函数B可见可使用。
- 但是Inner函数B作为了返回值,会在未来的某个程序点处使用。
- 此时Outer函数A的scope中实参和局部变量在栈上会消失,所以出现"闭包"概念就构造一个结构体去capture 外部变量。
所以,闭包是为了解决函数式语言中函数在使用变量时能看到哪些变量(变量作用域)的技术。
closure at python 🔗
1 #!/usr/bin/python3
2
3 shadowed_var = 10 #
4 def outer(x): #
5 shadowed_var = 20; #
6 def inner(y): #
7 tripple = 0 #
8 tripple = shadowed_var * 3 #
9 return x + y + tripple #
10 return inner #
11
12 fun = outer(1)
13 # x = 1, y = 2, tripple = 20 * 3
14 print(fun(2)) # 63
15 print("demonstration end. \n")
closure at rust 🔗
rust中在迭代器,启动线程等大量使用了closure。
与其他语言的闭包类似:闭包就是捕获外部变量的结构体,加一段代码。 closure 是结构体(捕获的变量)的语法糖,闭包逻辑部分在代码段中。
闭包去实现哪种Fn, FnMut, FnOncetrait与move无关,与如何捕获变量无关。
Fn FnMut FnOnce与闭包如何使用捕获到的值有关。
闭包的调用: Fn::call(第一个参数就是闭包结构体...)
// 移走匿名结构体中变量的closure实现 FnOnce
FnOnce::call_once(self, args: Args) -> Self::Output;
// 不会移走匿名结构体中变量但修改的closure实现 FnMut
FnMut::call_mut(&mut self, args: Args) -> Self::Output;
//不会修改匿名结构体中变量的closure实现 Fn
Fn: call(&self, args: Args -> Self::Output);
其他联想 🔗
PL闭包, regex 闭包 与 代数中的封闭
联想到闭包在pl,regex中出现过, 在代数里的封闭性也叫closure。
代数结构 等于 集合 、运算操作。加法运算和乘法运算是在自然数集和上是封闭的(closure)。
PL中的闭包是拥有自给的匿名结构体,闭包逻辑在代码区生成一段代码。
todo c, golang 中的闭包。