wil*_*ert 6 perl symbolic-references
为什么以下代码段可以正常工作?使用这个可能有什么邪恶?但是说真的,有什么理由,根本${}得到的代码被评估然后用作标量参考?
use strict;
no strict 'refs';
our $message = "Hello world!";
print "${ lc 'MESSAGE' }\n";Run Code Online (Sandbox Code Playgroud)
bri*_*foy 12
我们在Intermediate Perl中深入解释了这一点.
变量查找的一般语法是:
SIGIL BLOCK INDEXY-THING
Run Code Online (Sandbox Code Playgroud)
对于一个看起来像的简单标量:
print $ { foo };
Run Code Online (Sandbox Code Playgroud)
当您需要将变量名称与其周围的事物分开时,您可能已经看到过这种情况:
print "abc${foo}def\n";
Run Code Online (Sandbox Code Playgroud)
如果你只是在块中有一个Perl标识符而没有周围的混乱,你可以不用括号,这是常见的情况:
print $foo;
Run Code Online (Sandbox Code Playgroud)
但是,取消引用引用是一回事:
SIGIL BLOCK-RETURNING-REFERENCE INDEXY-THINGS
Run Code Online (Sandbox Code Playgroud)
如果您在块中获得的内容是引用,Perl会尝试取消引用它,就像您提出的那样:
my $ref = \ '12345';
print $ { $ref };
Run Code Online (Sandbox Code Playgroud)
这是一个真正的障碍,而不仅仅是糖.您可以在那里拥有任意数量的语句:
print $ { my $ref = \ '1234'; $ref };
Run Code Online (Sandbox Code Playgroud)
现在你不只是指定一个Perl标识符,所以Perl不会假设你给它一个标识符并且它执行代码并使用结果作为参考.考虑这些几乎相同的say陈述之间的区别:
use 5.010;
our $foo = "I'm the scalar";
sub foo { \ "I'm the sub" }
say ${foo};
say ${foo;};
Run Code Online (Sandbox Code Playgroud)
在第二个sayPerl看到分号时,意识到它不是标识符,将大括号内的代码解释为文本,并返回结果.由于结果是引用,它使用${...}取消引用它.你在哪里这样做并不重要,所以你在双引号字符串中这样做并不特别.
另外,请注意our那里.现在重要的是你要考虑更棘手的事情:
use 5.010;
our $foo = "I'm the scalar";
sub foo { \ "I'm the sub" }
sub baz { 'foo' }
say ${foo};
say ${foo;};
say ${baz;};
Run Code Online (Sandbox Code Playgroud)
Perl int代表最后say作为代码并且看到结果不是引用; 这是简单的字符串foo.Perl认为它不是一个参考,但它现在处于一个解除引用的上下文中,所以它做了一个符号引用(正如Greg Bacon描述的那样).由于符号引用使用符号表中的变量,因此$foo必须是包变量.
因为它很容易搞砸了,所以strict有一个方便的检查.但是,当你把它关掉的时候,当它咬你时不要感到惊讶.:)
在您将标识符(或标识符链)作为变量或子例程名称的一部分放置的任何地方,您可以使用BLOCK替换标识符,返回正确类型的引用.换句话说,前面的例子可以这样写:
Run Code Online (Sandbox Code Playgroud)$bar = ${$scalarref}; push(@{$arrayref}, $filename); ${$arrayref}[0] = "January"; ${$hashref}{"KEY"} = "VALUE"; &{$coderef}(1,2,3); $globref->print("output\n"); # iff IO::Handle is loaded不可否认,在这种情况下使用curlies有点傻,但BLOCK可以包含任意表达式,特别是下标表达式:
Run Code Online (Sandbox Code Playgroud)&{ $dispatch{$index} }(1,2,3); # call correct routine由于能够在简单的情况下省略curlies
$$x,人们常常会错误地将解除引用符号视为正确的操作符,并且想知道它们的优先级.但是,如果它们是,您可以使用括号而不是括号.事实并非如此.考虑下面的差异; case 0是案例1的简写版本,而不是案例2:Run Code Online (Sandbox Code Playgroud)$$hashref{"KEY"} = "VALUE"; # CASE 0 ${$hashref}{"KEY"} = "VALUE"; # CASE 1 ${$hashref{"KEY"}} = "VALUE"; # CASE 2 ${$hashref->{"KEY"}} = "VALUE"; # CASE 3案例2也具有欺骗性,因为您正在访问一个名为的变量
%hashref,而不是解引用$hashref它可能引用的哈希值.那将是案例3.
后来在"符号引用"中:
我们说如果它们是未定义的,那么引用会根据需要弹出,但我们没有说明如果已经定义了用作引用的值,但不是硬引用会发生什么.如果您将其用作参考,则将其视为符号引用.也就是说,标量的值被视为变量的名称,而不是指向(可能)匿名值的直接链接.
没关系,除非你使用符号引用。假设有以下代码:
my %messages = (hello => "Hello world!", bye => "Bye-bye, world!");
sub get_message_ref { return \$messages{$_[0]} }; # returns scalarref
print "${ get_message_ref('bye') }\n";
Run Code Online (Sandbox Code Playgroud)
同意,它的用处对于 scalarrefs 来说并不明显,但是对于 arrayrefs 来说非常有用。
print "keys: @{[keys %messages]}\n";
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3725 次 |
| 最近记录: |