perl - 为什么 Perl 在字符串插值期间计算 ${...} 中的代码?

标签 perl symbolic-references

为什么下面的代码片段能起作用?使用这个可能会带来什么邪恶呢?但说真的,是否有任何原因, ${} 中的代码会被评估然后用作标量引用?

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/

相关文章:

perl - 我应该从 CGI.pm 迁移到 CGI::Simple 吗?

matlab - Matlab中变量的符号声明

perl - 如何在 Perl 中修改二进制标量的特定部分?

perl - 如何将函数传递给构造函数

mysql - 如何在 perl 脚本中使用 UTF8 连接到 MySQL?

java - 解析后的引用(即针对符号引用的直接内存地址)存储在 JVM 中的位置?

syntax - 内省(introspection)模块/类/等的替代语法

java - Java 中的符号引用

git - Git 符号引用的推荐用法是什么?

Perl 和 Rose::DB Postgres 事务