[点点搬家]关于闭包(closure)的小知识
2015-01-06 17:28
218 查看
[两年前的博客,那时候对于java里没有的东西充满了好奇]
先说数学意义把,很简单。
闭合:如果一个集合中的数据对于一个运算后还处于这个集合中,则该集合对于该运算闭合。如实数对减法和加法都闭合,但是自然数则不然。
闭包:如果某个集合S对一个运算不闭合,通常可以找到包含这个S的最好闭合集合,则这个闭合集合叫做集合S对于这个运算的闭包。还如同上面的例子,自然数的集合{1,2,3,4,5,6,7,8,9}对于减法的闭包应该是{-8,-7.....7,8} (如果我没算错的话……)
行,数学上就不深究了,没啥意义,看程序的吧。
程序上来说,闭包的意义在于一个代码块可以包含自由变量——因为自由变量被包含在代码块中了,丫就不能被释放了。
不同语言对闭包的支持程度不一样,用perl来举例,perl用匿名subroutine来实现闭包:
上面代码中$greeting是lexcial的(用my修饰,必须用my),且属于那个匿名代码块,所以这个变量就释放不鸟了。想让闭包这个功能有意义,把hello world替换掉,变成一个输入的变量:
鸟然了吧,在perl里,闭包就是这么用地。
那该问了,在perl里用闭包意义何在?如上述代码,可以用generate_greeting($arg1,$arg2)代替,为啥用闭包呢?其实仔细思考一下,两个还是有细微差别的,回归闭包本质,$rs1与$rs2是包含了自己持有的变量的,而generate_greeting("hello","world")与generate_greeting("my fair", "lady")只是一个模板,没有任何数据。这是两者的一个区别,既然我在比包中有了数据,就能增加一些有趣的功能,下面我们继续修改这段代码:
输出为:
可以看到,拥有了数据就相当于拥有了状态,而不再是单一的一个输入对应唯一一个输出的机制了,这个特性是对立于纯函数的。
closure的一个应用就是grep函数:
这里就传递了一个闭包进去,是一种十分泛化的做法。
再如,更加常见的地方就是异步调用,利用闭包来填补事件驱动程序与顺序程序之间的沟壑。虽然用sub直接当callback既可以了,如果利用带闭包的callback就可以更加的smart,后续代码未来再补充
先说数学意义把,很简单。
闭合:如果一个集合中的数据对于一个运算后还处于这个集合中,则该集合对于该运算闭合。如实数对减法和加法都闭合,但是自然数则不然。
闭包:如果某个集合S对一个运算不闭合,通常可以找到包含这个S的最好闭合集合,则这个闭合集合叫做集合S对于这个运算的闭包。还如同上面的例子,自然数的集合{1,2,3,4,5,6,7,8,9}对于减法的闭包应该是{-8,-7.....7,8} (如果我没算错的话……)
行,数学上就不深究了,没啥意义,看程序的吧。
程序上来说,闭包的意义在于一个代码块可以包含自由变量——因为自由变量被包含在代码块中了,丫就不能被释放了。
不同语言对闭包的支持程度不一样,用perl来举例,perl用匿名subroutine来实现闭包:
sub generate_greeting { my($greeting) = "hello world"; return sub {print $greeting}; } $rs = generate_greeting(); &$rs(); # Prints "hello world"
上面代码中$greeting是lexcial的(用my修饰,必须用my),且属于那个匿名代码块,所以这个变量就释放不鸟了。想让闭包这个功能有意义,把hello world替换掉,变成一个输入的变量:
sub generate_greeting { my($greeting) = @_; # $greeting primed by arguments return sub { my($subject)= @_; print "$greeting $subject \n"; }; } $rs1 = generate_greeting("hello"); $rs2 = generate_greeting("my fair"); # $rs1 and $rs2 are two subroutines holding on to different $greeting's &$rs1 ("world") ; # prints "hello world" &$rs2 ("lady") ; # prints "my fair lady"
鸟然了吧,在perl里,闭包就是这么用地。
那该问了,在perl里用闭包意义何在?如上述代码,可以用generate_greeting($arg1,$arg2)代替,为啥用闭包呢?其实仔细思考一下,两个还是有细微差别的,回归闭包本质,$rs1与$rs2是包含了自己持有的变量的,而generate_greeting("hello","world")与generate_greeting("my fair", "lady")只是一个模板,没有任何数据。这是两者的一个区别,既然我在比包中有了数据,就能增加一些有趣的功能,下面我们继续修改这段代码:
use strict; use warnings; use 5.010; sub generate_greeting { my($greeting) = @_; # $greeting primed by arguments return sub { my($subject)= @_; $greeting .= '~'; print "$greeting $subject \n"; }; } my $rs1 = generate_greeting("hello"); my $rs2 = generate_greeting("my fair"); for(1..10){ &$rs1 ("world") ; &$rs2 ("lady") ; }
输出为:
hello~ world my fair~ lady hello~~ world my fair~~ lady hello~~~ world my fair~~~ lady hello~~~~ world my fair~~~~ lady hello~~~~~ world my fair~~~~~ lady hello~~~~~~ world my fair~~~~~~ lady hello~~~~~~~ world my fair~~~~~~~ lady hello~~~~~~~~ world my fair~~~~~~~~ lady hello~~~~~~~~~ world my fair~~~~~~~~~ lady hello~~~~~~~~~~ world my fair~~~~~~~~~~ lady
可以看到,拥有了数据就相当于拥有了状态,而不再是单一的一个输入对应唯一一个输出的机制了,这个特性是对立于纯函数的。
closure的一个应用就是grep函数:
my @evenList = grep {$_ % 2 == 0} (1..10);
这里就传递了一个闭包进去,是一种十分泛化的做法。
再如,更加常见的地方就是异步调用,利用闭包来填补事件驱动程序与顺序程序之间的沟壑。虽然用sub直接当callback既可以了,如果利用带闭包的callback就可以更加的smart,后续代码未来再补充
相关文章推荐
- javascript基础知识复习1-关于闭包
- [点点搬家]初试mod_perl+apache 之三 关于使用Apache-DB-0.14 调试
- 关于JAVASCRIPT中的闭包(Closure)!
- JavaScript变量作用域(Variable Scope)和闭包(closure)的基础知识
- 关于lua的闭包(Closure)和Upvalue
- 关于闭包(closure)的一些概念
- 关于JavaScript的闭包(closure)
- 关于for循环与闭包的一点点点笔记
- 学习Javascript闭包(Closure)知识
- 关于lua的闭包(Closure)和Upvalue
- 关于js的一些基本知识(类,闭包,变量)
- 关于程序化交易的点点知识
- 关于SQL SERVER 2000的一些基本知识(1)——简单的SQL语句
- 关于C++准备知识
- GeoGraphics文档中关于坐标系统的一些知识
- 作为一个程序员,有些知识你应该知道----关于并发和数据库封锁
- 每一个软件开发人员绝对必须掌握的关于 Unicode 和字符集的最基础的知识
- 转载:关于linux图形界面的基本知识
- 关于 Unicode 和字符集的最基础的知识
- 关于jxl的一点知识