Perl中的闭包(closure)
什么是闭包,“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 that retains 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 was created"), 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 -w
use strict;{my $inc = 10;sub incr {print "$inc\n";$inc++;}
}incr();
incr();#prints:
#10
#11
这个例子说明命名函数默认是全局的,即使是定义在一个block里面。我们不能引用变量$inc,但是却可以调用函数。
#!/usr/bin/perl -w
use 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 -w
use 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 -w
use 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_ref
sub 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
Perl中的闭包(closure)相关推荐
- python中的闭包(closure)
背景 本文尝试介绍Python中的闭包(closure),包括闭包是什么? 为什么要使用闭包?如何使用闭包? 嵌套函数及非局部变量 在介绍闭包之前,需要先明白什么是嵌套函数和非局部变量.在一个函数(f ...
- javascript中的闭包closure详解
文章目录 简介 函数中的函数 Closure闭包 使用闭包实现private方法 闭包的Scope Chain 闭包常见的问题 闭包性能的问题 总结 简介 闭包closure是javascript中一 ...
- lua中的闭包(closure或者匿名函数)的作用
闭包和upvalue lua构建一个新的函数时, 会创建一个函数对象, 其中包含了函数本身的原型还有函数使用到的外部变量或者常量. 当这个新的函数处于某个函数内部, 我们将这个对象称之为闭包, 它所引 ...
- 详解js中的闭包(closure)以及闭包的使用
作用域链 我们知道在js中作用域分为全局作用域与局部作用域,作用域链的访问规则为从内到外,也就是说如果当前的作用域中没有该变量或者方法,则会在包含该作用域的外层作用域中,一层一层的向上找,直到wind ...
- python 返回函数 闭包_python中闭包Closure函数作为返回值的方法示例
前言 首先看看闭包的概念:闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数.这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外 ...
- python闭包的应用场景_简单谈谈Python中的闭包
Python中的闭包 前几天又有人留言,关于其中一个闭包和re.sub的使用不太清楚.我在脚本之家搜索了下,发现没有写过闭包相关的东西,所以决定总结一下,完善Python的内容. 1. 闭包的概念 首 ...
- [译]Javascript中的闭包(closures)
本文翻译youtube上的up主kudvenkat的javascript tutorial播放单 源地址在此: https://www.youtube.com/watch?v=PMsVM7rjupU& ...
- 【Groovy】闭包 Closure ( 闭包类 Closure 简介 | this、owner、delegate 成员区别 | 静态闭包变量 | 闭包中定义闭包 )
文章目录 总结 一.静态闭包变量 1.执行普通闭包变量 2.执行静态闭包变量 二. 在闭包中定义闭包 三. 完整代码示例 总结 在闭包中 , 打印 this , owner , delegate , ...
- 【Groovy】闭包 Closure ( 闭包调用 与 call 方法关联 | 接口中定义 call() 方法 | 类中定义 call() 方法 | 代码示例 )
文章目录 总结 一.接口中定义 call() 方法 二.类中定义 call() 方法 三.完整代码示例 总结 在 实例对象后使用 " () " 括号符号 , 表示调用该实例对象的 ...
最新文章
- iOS之常用的正则表达式
- 打造 .NET Core 链接转发服务
- JavaScript学习笔记(七)--函数
- numpy 常用api(一)
- 2017蓝桥杯B组:最长公共子序列(动态规划详解(配图))
- span的title标签中的换行
- 手动打印日志及日志等级相关-1
- AlterID.exe解决teamview商业使用
- 【python快速入门】—唐宇迪课程笔记
- matlab 螺纹,关于螺纹边缘提取及参数测量
- Python 判断素数(质数)的方法讲解
- 鸟哥的Linux私房菜
- 理解RoIAlign实际操作
- Android专利战对大陆手机产业的影响
- 2023年了,推荐 5 款 API 管理工具
- 假设一个录像厅有0,1,2三种不同的录像片可由观众选择放映。录像厅的放映规则为: 1)任何时刻最多只能放映一种录像片,正在放映的录像片是自动循环放映的。最后一个观众主动离开时结束当前录像片的放映。
- 在阿里讲了5小时运营后,我想试着重新解读“运营”
- 「数字电子技术基础」2.数制和码制
- 7-5 查询自动售货机中商品的价格
- Python 数据分析微专业课程--项目03 视频网站数据清洗整理和结论研究