Subroutine Signatures - 子例程参数署名

There's more than one way to do it!
https://metacpan.org http://perlmonks.org
回复
头像
523066680
Administrator
Administrator
帖子: 573
注册时间: 2016年07月19日 12:14
联系:

Subroutine Signatures - 子例程参数署名

帖子 523066680 »

在 Mojo::UserAgent 官方示例中,有一段非阻塞请求的示例
# Non-blocking request $ua->get('mojolicious.org' => sub ($ua, $tx) { say $tx->result->dom->at('title')->text }); Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
其中,sub ($ua, $tx) {} 的形式之前还未在Perl中用过。运行出现错误提示
> Mojo::Reactor::Poll: I/O watcher failed: Can't call method "result" on an undefined value

后来写爬虫要用到非阻塞请求,又懒得探索,就自己改成传统方式,局部变量接收默认回调参数 $ua, $tx
$ua->get('mojolicious.org' => sub {my ($ua, $tx) = @_; say $tx->result->dom->at('title')->text });
不过很快遇到新的需求,抓取的大量数据要分门别类地存储到指定的目录指定的文件,如何告诉这个回调函数指定的文件路径和文件名?想到了闭包,这样便可以传递更多参数。

以下代码根据 %list 中的城市名单,获取不同城市的物流数据并保存到相应JSON文件。
my $wdir = "D:/blah"; for my $city ( keys %list ) { my $name = sprintf "%s/%s.json", $wdir, gbk($city); $query->{"toCountryId"} = $ct_code->{$city}; # 城市ID 更新到请求数据中 $res = $ua->post( $url, to_json( $query ), closure->( $name ) ); } $loop->start unless $loop->is_running; sub closure { my ( $file ) = @_; return sub { my ($ua, $tx) = @_; printf "%s\n", $file; write_file( $file, $tx->result->body ); } }
其实在 Mojolicious::Guides 中有相关介绍,只是之前忽视了,
https://docs.mojolicious.org/Mojolicious/Guides

>Signatures
On Perl 5.20+ you can also use the `-signatures` flag with Mojo::Base to enable support for subroutine signatures. Signatures are used in all examples for clarity, even when `-signatures` is omitted for brevity.

通过该特性以达到简洁代码的目的,(闭包似乎还是省不了)
my $wdir = "D:/blah"; for my $city ( keys %list ) { my $name = sprintf "%s/%s.json", $wdir, gbk($city); $query->{"toCountryId"} = $ct_code->{$city}; # 城市ID 更新到请求数据中 $res = $ua->post( $url, to_json( $query ), closure->( $name ) ); } $loop->start unless $loop->is_running; sub closure ($file) { return sub ($ua, $tx) { printf "%s\n", $file; write_file( $file, $tx->result->body ); } }
其他参考 Announcing Perl 7
回复

在线用户

正浏览此版面之用户: 没有注册用户 和 3 访客