• 第四章 子例程引用与闭包


    和普通变量一样,子例程(subroutine)可以是有名的也可以是匿名的,而且Perl 语法上支持对任何一种类型的引用。

    这种引用很像C语言中指向函数的指针,它可以被用来创建如下复杂的结构:

    闭包(Closure).闭包是这样一种字例程,创建时,它将包含其子例程的环境打包。

    子例程引用:

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

    对有名子例程的引用:

    我们前面就已经讲过,要创建对现存变量的引用,只需给它加上反斜杠前缀。对于子例程也大致如此,

    如&mysub 就是对&mysub的引用。又比如:

    [root@master perl]# cat m12.pl
    sub greet {
    print “hello ”;
    }
    rs=&greet;printrs,” ”;
    rs=&greet();printrs,” ”;

    [root@master perl]# perl m12.pl
    CODE(0x25c0c48)
    hello
    SCALAR(0x25ac178)

    有重要的一点需要说明,我们并没有在此调用子例程greet,这和创建对标量变量的引用时一样,也没有计算标量变量的值。

    与下面带有圆括号的代码作一对比:

    $rs=&greet();

    对匿名子例程的引用:

    你只需要省略掉子例程声明中的过程名即可创建匿名子例程。除了这一点外,其声明同有名子例程完全一样。

    [root@master perl]# cat m12.pl
    rs=sub{  
     print “hello  ”;  
    };  
    &
    rs;
    [root@master perl]# perl m12.pl
    hello

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

    对于子例程引用的间接访问(dereference)将会间接的调用该子例程。

    和数据引用一样,Perl并不关心$rs指向的有名还是无名的子例程:

    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” },
    );

    这里是子程序的引用:

    闭包:

    [root@master perl]# cat m13.pl
    greeting=helloworld;rs = sub{
    print greeting;  
    };  
    &
    rs();
    [root@master perl]# perl m13.pl
    hello world[root@master perl]#

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

    [root@master perl]# cat m15.pl
    sub generate_greeting{
    return sub {print “xxxxxxx”};
    }

    rs=generate_greeting();  
    &
    rs();
    [root@master perl]# perl m15.pl
    xxxxxxx

    闭包就是一些保留这在其创建时所在域中需要的变量。

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

    [root@master perl]# cat m16.pl
    callbackproc=subprintxxxxxxxx ;;printcallback_proc,” ”;
    print &$callback_proc;

    [root@master perl]# perl m16.pl
    CODE(0x7c9c60)

    xxxxxxxx

    [root@master perl]# cat m17.pl
    sub gererate_greeting{
    my (greeting) = “hello world”;  
      return sub{print
    greeting};
    }

    rs=gererate_greeting();  
    &
    rs();

    [root@master perl]# perl m17.pl
    hello world[root@master perl]#

    sub{print $greeting} 这里是引用

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

    闭包的应用;

    闭包以两种似乎毫不相关的方式来应用,最常见的用法是用”智能” 回调子例程。

    将闭包用作”智能”回调

    由于闭包是一些包含少量私有数据的子例程引用,因为它们可以方便的应用在图形用户界面的回调过程中。

    举例来说,你使用Tk工具包创建了一个按钮,并赋予它一个指向子例程的引用。当按钮被按下时将回调该子例程。

    CreateButton 创建了一个GUI的按钮,并提供给它一个指向匿名子例程的引用($callback_proc),

    它将依附于其环境中的my变量title.,,使title的值。

    闭包和对象的对比:

    对象通俗的定义就是一组数据与函数的集合,数据提供对象函数操作的环境。比如,

    $button->setForground(“yellow”)中,>setForground函数会自动知道你指的是哪个按钮。

  • 相关阅读:
    面试中变相考算法复杂度
    黑马程序猿——JAVA面向对象的特性:封装,继承,多态
    Supermap 组合单值专题图与标签专题图演示样例
    线段树 hdu3642 Get The Treasury
    servlet学习(1)
    Androidbutton事件的五中写法总结
    Java多线程的调度策略
    linux命令行学习-dig(DNS查询器)
    kettle(一)概述
    学习C语言,困难吗?
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13351343.html
Copyright © 2020-2023  润新知