Journal(2005) | Blog(2006) | RandomLink | WhoAmI | LiveBookmark | HomePage

<<Previous: 用 CGI::Untaint 检测 params  >>Next: Larry Wall Quotes

符号表, local和my, * 与 \$

Category: Basic   Keywords: Symbol Table

Guess the result

如果你知道下面这几段代码的结果是什么就不用看本文了。
  1. 
    $bar = 'a';
    *foo = *bar;
    {
        local $bar = 'b';
        print $foo;
    }
    
    显示结果/Show result: b
  2. 
    $bar = 'a';
    *foo = \$bar;
    {
        local $bar = 'b';
        print $foo;
    }
    
    显示结果/Show result: a
  3. 
    $bar->{'t'} = 'a';
    *foo = \$bar;
    {
        local $bar->{'t'} = 'b';
        print $foo->{'t'};
    }
    
    显示结果/Show result: b
  4. 
    $bar = a;
    *foo = *bar;
    {
        my $bar = b;
        print $foo;
    }
    
    显示结果/Show result: a

Reference

详细描述



符号表如上图所示,获取符号表里的值必须提供名字和类型两个参数。

首先谈 * 与 $\ 的区别:
*a = *b 后,你可以用 ($@%&)a 来得到 b 所有的变量,数组,散列,子程序,格式,文件句柄和文件句柄。
*a = \$b 只允许用 $a 得到 $b,而 @a 是不同于 @b 的。
举个简单的例子如下:

$a = 1;@a = qw/a b/;
*b = *a;
*c = \$a;

print join('-', $b, scalar @b, $c, scalar @c);
得到的结果为 1-2-1-0
这是因为 $c 等同于 ${\$a} 所以与 $a 等价;而 @c 等同于 @{\$a} 而不能等同于 @a.

其次来讲讲 local 与 my 的区别:
local 能操作 symbol table而 my 不行,这就是代码1与代码4的区别。

加了注释的代码

  1. 
    $bar = a; 
    *foo = *bar; # foo 是 bar 的别名
    {
        local $bar = b; # local 能改变符号表里的名为bar类型为Scalar的值为 2
        print $foo; # 求符号表中名为foo(对应到bar)类型为Scalar的值
    }
    
  2. 
    $bar = 'a';
    *foo = \$bar; # 引用是让 foo 对应 $bar 的值 a,引用的特点是指向$bar变量的值而不是$bar变量的名字(bar)
    {
        local $bar = 'b'; # local 改变的是 $bar 的值
        print $foo; # 根据引用对应变量值而非变量名的特点,foo 还是指向 a
    }
    # 将这面这段代码与下面的比较或许会明白一点
    $bar = 'a';
    $foo = \$bar;
    {
        local $bar = 'b';
        print $$foo; # 这里输出的就是 a
    }
    

    The reference points to the value of $bar, not the variable itself or its name.
    在local前,bar,foo的关系如图,在local后,就是图中的那条红线断了。foo指向的还是a.
    关于引用更详细的资料,参见 Effective Perl - Reference

  3. 
    $bar->{'t'} = 'a';
    *foo = \$bar;
    {
        local $bar->{'t'} = 'b';
        print $foo->{'t'};
    }
    # 比较下面的代码:
    $bar->{'t'} = 'a';
    $foo = \$bar;
    {
        local $bar->{'t'} = 'b';
        print $$foo->{'t'}; # 这里输出的是 b
    }
    
  4. 
    $bar = 'a';
    *foo = *bar;
    {
        my $bar = 'b'; # my 不操作符号表, 符号表里名为bar类型为Scalar 值还是 1
        print $foo; # 求符号表中名为foo(对应到bar)类型为Scalar的值
    }
    
这四段代码看起来是考符号表 Symbol Table, 但更大程度是要理解引用。

<<Previous: 用 CGI::Untaint 检测 params  >>Next: Larry Wall Quotes

Options: +Del.icio.us

Related items Created on 2005-04-18 22:11:20, Last modified on 2005-04-19 00:49:11
Copyright 2004-2005 All Rights Reserved. Powered by Eplanet && Catalyst 5.62.