设为首页 收藏本站
查看: 543|回复: 0

[经验分享] Perl中的闭包(closure)

[复制链接]

尚未签到

发表于 2017-5-17 11:29:56 | 显示全部楼层 |阅读模式
  什么是闭包,“This is a notion out of the Lisp world that says if you define an anonymous function in a particular lexical context, it pretends to run in that context even when it's called outside of the context.”【2】。在面向对象的语言里面,“A closure is a callable object thatretains information from the scope in which it was created. From this definition, you can see that an inner class is an object-oriented closure, because it doesn’t just contain each piece of information from the outer-class object ("the scope in which it wascreated"), but it automatically holds a reference back to the whole outer-class object, where it has permission to manipulate all the members, even private ones.”【3】

  先看这个例子:
#!/usr/bin/perl -wuse strict;{my $inc = 10;sub incr {print "$inc\n";$inc++;}}incr();incr();#prints:#10#11
这个例子说明命名函数默认是全局的,即使是定义在一个block里面。我们不能引用变量$inc,但是却可以调用函数。#!/usr/bin/perl -wuse strict;sub make_incr {my $inc = shift;return sub { print "$inc\n"; $inc++ };}my $c1 = make_incr(10);my $c2 = make_incr(20);$c1->();$c2->();$c1->();$c2->();#prints:#10#20#11#21这个例子我们看到了,Perl的函数返回其实是一个匿名函数引用,这个就是magic所在了。这个也是Perl如何实现闭包的。
#!/usr/bin/perl -wuse strict;sub exclaim {my $prefix = shift;return sub { print "$prefix $_[0]!\n" };}my $batman = exclaim('Indeed');my $robin  = exclaim('Holy');$robin->('Mackerel');    # prints: Holy Mackerel!$batman->('Robin');      # prints: Indeed Robin!  那么闭包有什么作用呢?以下摘自“Learning Perl Objects, References & Modules”的第6章【1】:
  用法一 在subroutine中返回subroutine的引用,通常作为回调函数:
use File::Find;sub create_find_callbacks_that_sum_the_size {my $total_size = 0;return ( sub { $total_size += -s if -f }, sub { return $total_size } );}my ( $count_em, $get_results ) = create_find_callbacks_that_sum_the_size();find( $count_em, "bin" );my $total_size = &$get_results();print "total size of bin is $total_size \n";这段代码用于计算某个目录下所包含的所有文件的大小之和.  用法二 使用闭环变量作为输入,用作函数生成器,来生成不同的函数指针:
#!/usr/bin/perl -wuse strict;sub print_bigger_than {my $minimum_size = shift;return sub { print "$File::Find::name/n" if -f and -s >= $minimum_size };}my $bigger_than_1024 = print_bigger_than(1024);find( $bigger_than_1024, "bin" );print_bigger_than在这里相当于一个函数生成器,不同的输入变量可以生成不同的函数指针.这里生成了一个可以打印出文件大小大于1024字节文件名的回调函数.  用法三 作为静态局部变量使用,提供了c语言静态局部变量的功能:
BEGIN {my $countdown = 10;sub count_down { $countdown-- }sub count_remaining { $countdown }}这里用到了关键字BEGIN. BEGIN的作用就是,当perl编译完这段代码之后,停止当前编译,然后直接进入运行阶段,执行BEGIN块内部的代码.然后再回到编译状态, 继续编译剩余的代码. 这就保证了无论BEGIN块位于程序中的哪个位置,在调用count_down之前,$countdown被确保初始化为10.  最后附上一个相当cool的例子,来在“Perl Best Practices”:
# Generate a new sorting routine whose name is the string in $sub_name# and which sorts on keys extracted by the subroutine referred to by $key_sub_refsub make_sorter {my ( $sub_name, $key_sub_ref ) = @_;# Create a new anonymous subroutine that implements the sort...my $sort_sub_ref = sub {# Sort using the Schwartzian transform...return map { $_->[0] }                # 3. Return original valuesort     { $a->[1] cmp $b->[1] }    # 2. Compare keysmap { [ $_, $key_sub_ref->() ] }    # 1. Extract key, cache with value@_;                                 # 0. Perform sort on full arg list};# Install the new anonymous sub into the caller's namespaceuse Sub::Installer;caller->install_sub( $sub_name, $sort_sub_ref );return;}# and then...make_sorter( sort_sha => sub { sha512($_) } );make_sorter( sort_ids => sub { /^ID:(\d+)/ } );make_sorter( sort_len => sub { length } );# and later...@names_shortest_first = sort_len(@names);@names_digested_first = sort_sha(@names);@names_identity_first = sort_ids(@names);
  参考:

  • http://blog.csdn.net/mac_philips/article/details/6058946
  • http://unlser1.unl.csi.cuny.edu/faqs/perl-faq/Q3.14.html
  • Think in Java, 4th
  • http://www.itworld.com/nl/perl/08302001/
  • http://docstore.mik.ua/orelly/perl/advprog/ch04_03.htm

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-378487-1-1.html 上篇帖子: java调用perl方式二 下篇帖子: perl 实现查找内置 package
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表