[点点搬家]关于闭包(closure)的小知识

[两年前的博客,那时候对于java里没有的东西充满了好奇]


先说数学意义把,很简单。

闭合:如果一个集合中的数据对于一个运算后还处于这个集合中,则该集合对于该运算闭合。如实数对减法和加法都闭合,但是自然数则不然。

闭包:如果某个集合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,后续代码未来再补充

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值