Perl中的閉包(closure)

來源:互聯網
上載者:User

什麼是閉包,“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 -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 value  sort     { $a->[1] cmp $b->[1] }    # 2. Compare keys  map { [ $_, $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);

參考:

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.