为什么下面的代码片段能起作用?使用这个可能会带来什么邪恶呢?但说真的,是否有任何原因, ${}
中的代码会被评估然后用作标量引用?
use strict;
no strict 'refs';
our $message = "Hello world!";
print "${ lc 'MESSAGE' }\n";
最佳答案
我们在 Intermediate Perl 中对此进行了深入解释。 .
变量查找的一般语法是:
SIGIL BLOCK INDEXY-THING
对于一个简单的标量,如下所示:
print $ { foo };
当您需要将变量名称与其周围的内容分开时,您可能已经看到过这一点:
print "abc${foo}def\n";
如果 block 中只有一个 Perl 标识符并且周围没有困惑,则可以省略大括号,这是常见的情况:
print $foo;
但是,这与取消引用引用是一样的:
SIGIL BLOCK-RETURNING-REFERENCE INDEXY-THINGS
如果你在 block 中得到的东西是一个引用,Perl 会尝试像你要求的那样取消引用它:
my $ref = \ '12345';
print $ { $ref };
那是一个真正的 block ,而不仅仅是糖。您可以在其中添加任意数量的语句:
print $ { my $ref = \ '1234'; $ref };
现在您不只是指定 Perl 标识符,因此 Perl 不会假设您给它一个标识符,它会执行代码并使用结果作为引用。考虑一下这些几乎相同的 say
语句之间的差异:
use 5.010;
our $foo = "I'm the scalar";
sub foo { \ "I'm the sub" }
say ${foo};
say ${foo;};
在第二个 say
中,Perl 看到分号,意识到它不是标识符,将大括号内的代码解释为文本,并返回结果。由于结果是一个引用,因此它使用 ${...}
来取消引用它。在哪里执行此操作并不重要,因此在双引号字符串内执行此操作并不特殊。
另外,请注意那里的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;};
Perl 将最后一个 say
解释为代码,并发现结果不是引用;它是简单的字符串foo
。 Perl 认为它不是引用,但它现在处于取消引用上下文中,因此它执行符号引用(如 Greg Bacon describes )。由于符号引用使用符号表中的变量,因此 $foo
必须是包变量。
由于很容易搞砸,因此 strict
有一个方便的检查方法。然而,当你把它关掉时,当它咬你时不要感到惊讶。 :)
关于perl - 为什么 Perl 在字符串插值期间计算 ${...} 中的代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2332815/