免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 4699 | 回复: 24
打印 上一主题 下一主题

从一段 AnyEvent 代码看闭包的使用 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-06-23 00:28 |只看该作者 |倒序浏览
本帖最后由 3P主义 于 2012-06-23 12:15 编辑

闭包就是带局部状态的函数,利用闭包,可以传送大量数据给函数。相对于传参方式,主要有以下两个优点:
1. 传送的数据量大。
2. 灵活,能突破参数个数的限制。

上述的优点2在回调代码中更明显,因为回调函数接受的参数都已确定了,不能再传递额外的参数。

以下用 AnyEvent::HTTP 演示闭包的使用,代码中一共有 1000 个关键词要查询,创建了 $cocurrent 个回调函数,每个回调函数都引用着外部的 @words 和 $word ,注意回调函数是怎么再次回调自身的
  1. #!/usr/bin/perl

  2. use strict;
  3. use warnings;
  4. use AnyEvent;
  5. use AnyEvent::HTTP;


  6. my $cocurrent = 100;    # 并发数
  7. my @words = map { "keyword" . $_ } (1 .. 1000); # 待查询的关键词

  8. my $cv = AnyEvent->condvar;
  9. my @c = splice(@words, 0, $cocurrent);

  10. foreach my $word (@c) { # 同时创建 $cocurrent 个请求
  11.     $cv->begin();
  12.     my $cb;
  13.     $cb = sub {
  14.         my ($content, $hdr) = @_;

  15.         print "Search: $word\tStatus: ", $hdr->{Status}, "\n";
  16.         $cv->end();

  17.         if (defined ($word = shift(@words))) {
  18.             $cv->begin();
  19.             http_get("http://www.baidu.com/s?wd=${word}", $cb);
  20.         }
  21.     };

  22.     http_get("http://www.baidu.com/s?wd=${word}", $cb);
  23. }

  24. $cv->recv();
复制代码
以上代码,每一个请求返回时,会重新创建一个新请求,并发数一直控制在 $cocurrent 个,工作良好。

论坛徽章:
2
射手座
日期:2014-10-10 15:59:4715-16赛季CBA联赛之上海
日期:2016-03-03 10:27:14
2 [报告]
发表于 2012-06-23 02:24 |只看该作者
回复 1# 3P主义


    8错,学习了~

论坛徽章:
0
3 [报告]
发表于 2012-06-23 03:34 |只看该作者
登个记 有时间来看

论坛徽章:
1
狮子座
日期:2013-12-16 16:09:24
4 [报告]
发表于 2012-06-23 05:18 |只看该作者
回复 1# 3P主义

学习了!
    请问  
1.  
my $cb;
   
$cb = sub {
这段能定义在foreach前面么?

2.
这个代码有没有递归特性(堆栈大小限制)?还是被AE给回避了递归?

论坛徽章:
0
5 [报告]
发表于 2012-06-23 08:39 |只看该作者
ttcn_cu 发表于 2012-06-23 05:18
回复 1# 3P主义

学习了!



1。 必须放在 foreach  中。
2。 没有用到递归。

论坛徽章:
2
CU大牛徽章
日期:2013-04-17 11:46:28CU大牛徽章
日期:2013-04-17 11:46:39
6 [报告]
发表于 2012-06-23 09:59 |只看该作者
学习了,一直不太清楚何为闭包?

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
7 [报告]
发表于 2012-06-23 10:13 |只看该作者
这程序可读性咋那么差呢?

写成下面这样不好吗?
  1. #!/usr/bin/perl

  2. use strict;
  3. use warnings;
  4. use AnyEvent;
  5. use AnyEvent::HTTP;

  6. my $cocurrent = 100;    # 并发数
  7. my @todoList = map { "keyword" . $_ } (1 .. 1000); # 待查询的关键词

  8. my $cv = AnyEvent->condvar;

  9. doit() foreach 1..$cocurrent;

  10. sub doit{
  11.     my $word = shift @todoList;
  12.     return if not defined $word;

  13.     $cv->begin;
  14.     http_get( "http://www.baidu.com/s?wd=$word", sub { done( $word, @_ ) } );
  15. }

  16. sub done {
  17.     my ($word, $content, $hdr) = @_;

  18.     $cv->end();
  19.     print "Search: $word\tStatus: ", $hdr->{Status}, "\n";
  20.     doit();
  21. }
复制代码

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
8 [报告]
发表于 2012-06-23 10:14 |只看该作者
记住:Don't repeat yourself

论坛徽章:
0
9 [报告]
发表于 2012-06-23 10:26 |只看该作者
时间和乳沟一样,挤一挤还是有的。

ding   支持

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
10 [报告]
发表于 2012-06-23 11:21 |只看该作者
本帖最后由 py 于 2012-07-04 14:50 编辑

回复 7# flw

看到楼主这个帖子我有一个问题。

用Coro+AnyEvent::HTTP可以写出一样功能的代码,两者都是非阻塞。这样一来,Coro就是可有可无了。Coro的优势是什么?(答案见17楼)
   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP