<perl> 符号引用

1 for (1..5){
2   $name="$_";
3   ${"var".$name}="Hello,this is VAR $_!";
4 }
5 print $var3;  #Hello,this is VAR 3!

可以用这个实现动态定义新变量。

对于一般的符号引用,可以省略{}:

$name="some";
$$name = 3;
#${$name}=3;   # same above
#$some=3;         # same above
print $some;

注意:一旦用了use strict; 符号引用就会失效!

 

 

参考(转载):

==通过子程序的引用调用子程序=============================================

原链接

假如我有一个子过程,定义如下:

sub test_sub {
    print "test";
}

我又有一个变量:

$test = "test_sub";

这个 $test 的值刚好就是上面子过程的名称。既然我通过 $test 知道了这个子过程名称,我可以通过 $test 达到调用这个子过程的目的吗?也就是说,我让用户从命令行里输入一个子过程的名称,然后就可以根据这个名称来调用相对应的子过程。

方法一,直接根据用户输入的子过程名来调用该子过程。

完整的例子代码如下:

use warnings;
no strict 'refs';

sub test_sub {
    print "test";
}

$test = "test_sub";

$test->();

&{$test}();  #anyway to invoke the subroutine

这里要注意,需要用

no strict 'refs';

这个语句,否则脚本不能运行,Perl 解释器会提示类似于下面的错误:

Global symbol “$test” requires explicit package name at test2.pl line 10.

 

方法二,更常规的做法是专门用一个起分派作用的散列,根据用户输入的请示而调用相应的子过程。例如下面的 %dispatcher 就起到了绑定识别标记与相应子过程引用的作用,通过这个唯一的标记 (key),我们可以很容易地找到对应的子过程引用

my %dispatcher = (
    sub_test => sub { print "test" },
);

然后可以用和方法一相同的语法来调用这个子过程:

$dispatcher{$sub_name}->();

下面是方法二的一个完整的例子:

use warnings;
use strict;

sub test_sub {
    print "test\n";
}

sub test_other {
    print "test other\n";
}

my %dispatcher = (
                  "test_sub"     => \&test_sub,
                  "test_other"   => \&test_other,
                 );

print "\nPlease enter the test case you want to test:\n";

while( my $cmd = <> )
{
    chomp($cmd);

    $dispatcher{$cmd}->() if exists $dispatcher{$cmd};
}

当然,方法二要比方法一优秀得多,它可以避免用户输入错误的子过程名而导致一系列的麻烦。

 

 

==符号引用===========================================================

一般来说,类似$$var的结构表示,$var是一个引用变量,而且程序员希望该表达式能够返回$var所指向的值。

假如$var不是引用变量的话会出现什么情况呢?Perl并不是断然打印出错误信息,而是尝试检查$var的值是否为一字符串。如果是,Perl将以该字符串作为正规的变量名与这个变量重新加以组合!考虑下面的例子:

    $x = 10;
    $var = "x";
    $$var = 30;    #$x的将被改为30,因为$var是一种符号引用

当对$$var进行间接访问时,Perl首先检查$var是否是引用,在这里它不是,而是字符串。于是Perl会再给该表达式一次机会:它将$var的内容当作变量标识符($x)。这样一来,最终$x的值就被修改成30了。


应当注意重要的一点是符号引用只对全局变量有效,而不能应用于那些用my标识为私有的变量。

符号引用对数组和散列表同样适用:

$var = "x";
@$var = (1,2,3);    #将@x的值设置为右边的枚举列表

注意$var前面的符号指示变量的存取类型:$$var等价于$x,@$var也等价于@x,这种特性非常有用。


对于那些在Perl的早期版本中就实现过此类功能的人来说,这要比使用eval更为高效。举例说明,你要在自己的脚本程序中,处理诸如“-Ddebug_level=3”的选项,并设置$debug_level变量。下面是其中的一种实现方式:

    while($arg = shift @ARGV){
        if($arg =~ /-D(\w+)=(\w+)/){
            $var_name = $1; $value = $2;
            $$var_name = $value; #更为简洁的可书写为:$$1 = $2;
        }
    }

从另一方面说,Perl竭尽全力使一个表达式正常工作,有时却于事无补。在前面的例子中,如果你所希望程序使用一个真正的引用,而不是字符串的话,那么你就会希望Perl能够指出这种情况而不是做任何的假定。幸运的的是,这种“急于求成”的方式科以被关闭。Perl有许多编译时指令和指示。strict编译指示将告诉Perl做严格的错误检查。你甚至科以指定需要进行严格检查的范围,其中之一就包括“refs”这一项:

    use strict 'refs';    #告诉Perl不允许符号引用
    $var = "x";
    $$var = 30;

无论何时你试图使用符号引用时均会导致运行时错误:

    can't use string ("x") as a SCALAR ref while "strict refs" in use at try.pl line 3

strict指令直至程序块结束仍然有效。可以通过输入no strict 或更明确的no strict 'refs'将其关闭。

转载于:https://www.cnblogs.com/danielrocks/p/3247295.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值