子例程引用和闭包

1. 调度表(dispatch table)  tk图形用户界面工具包

my (@frames,@button);  
    my %sub_of = (  
    "日志查询" => \&push_button2 ,  
        "VIEW MEMORY" => \&push_button2 ,  
        "VIEW DISK" => \&push_button3 ,  
        4 => sub{ print "program 4" },  
        5 => sub{ print "program 5" },  
        6 => sub{ print "program 6" },  
        7 => sub{ print "program 7" },  
        8 => sub{ print "program 8" },  
        9 => sub{ print "program 9" },  
); 

闭包(Closure) 闭包是这样一种子例程,创建时,它将包含其子例程的环境打包(包括所有它需要的和不局部与其本身的变量)


子例程引用

子例程并没有什么特别或神奇的地方,在这一节我们要学习如何创建对有名的和匿名的子例程的引用,

以及如何对它们进行间接访问


对有名子例程的引用:

我们前面就已经讲过,要创建对现存变量的引用,只需要给他加上反斜杠前缀。

对于子例程也大致如此,如\&mysub 就是对&mysub的引用

sub greet() {
  print "hello\n";
}

$rs=\&greet;


print &$rs;
print "\n";

print "2222222222\n";
my $str=&$rs();
print "\$str is $str\n";











对匿名子例程的引用:

Vsftp:/root/perl/13# cat a6.pl 
$rs = sub {
  print "Hello\n";
};

print &$rs;
print "\n";
Vsftp:/root/perl/13# perl a6.pl 
Hello
1

对子例程引用的间接访问:


Vsftp:/root/perl/13# cat a7.pl 
$rs = sub {
  my $a=shift;
  my $b=shift;
  return $a + $b;
};

print &$rs(10,20);
print "\n";
print $rs->(10,20);
print "\n";
Vsftp:/root/perl/13# perl a7.pl 
30
30

##定义下拉菜单
my %section = (
        "1-系统信息查询"        => ["日志查询","VIEW MEMORY","4"],
	"2-综合查询"         => [1],
	"3-收起菜单"         =>undef,
    
);



my (@frames,@button);
	my %sub_of = (
    "日志查询" => \&push_button2 ,
        "VIEW MEMORY" => \&push_button2 ,
        "VIEW DISK" => \&push_button3 ,
        4 => sub{ print "program 4" },
        5 => sub{ print "program 5" },
        6 => sub{ print "program 6" },
        7 => sub{ print "program 7" },
        8 => sub{ print "program 8" },
        9 => sub{ print "program 9" },
);

这段代码中的引用有些指向有名的子例程,有些则由于做的工作不多而直接以匿名子例程的形式嵌入其中。



闭包:

 不仅可以返回数据,Perl 的子例程海可以返回一个指向子例程的引用.

这是一种涉及匿名子例程和词法变量(my)的隐含特性,考虑下面的例子:

Vsftp:/root/perl/13# cat a8.pl 
$greeting ="hello world";
$rs = sub {
    print $greeting;
};

&$rs();
print "\n";
Vsftp:/root/perl/13# perl a8.pl 
hello world

在这个例子中,匿名子例程利用了全局变量$greeting,没什么特别


Vsftp:/root/perl/13# cat a9.pl 
sub generate_greeting {
   my $greeting = "hello world";
      return sub{print $greeting};
}

$rs=generate_greeting();
&$rs();
print "\n";
Vsftp:/root/perl/13# perl a9.pl 
hello world

任何定义在匿名子例程中表达式当时就已经使用了$greeting.

一个子例程块,从另外的角度讲,就是一块在以后某个时候调用的代码,

因此它将保留所有要在以后使用的变量。(从某种意义上说就是把它带走)



当该子过程后来被调用并执行 print $greeting时,他会记得当初子例程创建时

变量$greeting的值。


让我们再来改动下这段代码, 以便更好地理解闭包这个专业用语究竟能做什么:


Perl 创建的闭包恰好只针对(my) 词法变量而不对全局或者局部化(使用local)变量

posted @ 2016-12-01 10:01  czcb  阅读(179)  评论(0编辑  收藏  举报