为什么我不能使用Perl变量的值来访问词法变量名?

enn*_*ler 6 variables perl metaprogramming lexical

为什么打印42:

$answer = 42;
$variable = "answer";

print ${$variable} . "\n";
Run Code Online (Sandbox Code Playgroud)

但这不是:

my $answer = 42;
my $variable = "answer";

print ${$variable} . "\n";
Run Code Online (Sandbox Code Playgroud)

fri*_*edo 15

只能通过符号引用来定位包变量(在第一个示例中声明的类型).Lexical(my)变量不可能,这就是你的第二个例子失败的原因.

有关Perl中两个独立变量系统的运行方式,请参阅优秀文章Coping with Scoping.并且看到也非常好为什么使用变量变量名称为什么这是愚蠢的愚蠢.:)


Eri*_*rom 6

Perl有两个完全独立但基本兼容的变量系统,包变量(如第一个示例中)和词法变量(如第二个).除了另一个之外,每个人都可以做一些事情:

包变量是唯一可以是:

  1. 本地化的(带local)
  2. 用作符号引用的目标(OP的第二个例子不起作用的原因)
  3. 用作裸词(子定义,文件句柄)
  4. 与typeglobs一起使用(因为这就是符号真的在引擎盖下)

词汇变量是唯一可以被关闭的变量(用于词法闭包).

使用strict会有助于强制你声明包变量our,使差异更清晰.

有几次符号引用在Perl中很有用,大多数都围绕着操作符号表(比如import在模块中编写自己的,而不是Exporter在运行时使用猴子修补模块,各种其他元编程任务).所有这些都是高级主题.

对于其他任务,通常有更好的方法来执行此操作,例如使用哈希.一般的经验法则是始终运行,use warnings; use strict;除非您知道除了禁用部分编译指示之外没有任何其他方法(例如no strict 'refs';在尽可能小的范围内使用).


Phi*_*ter 5

问题是您不能使用符号引用来引用词汇变量。在两个示例中${$variable}都在寻找$main::answer。在第$answer一个包中,它是一个全局包,是的缩写$main::answer,因此引用可以找到它。第二个$answer是词法变量,它不存在于任何包中,因此引用找不到它。

perlref的符号引用”标题下有更多详细信息。


bri*_*foy 5

符号引用仅适用于包变量.符号表不跟踪词汇变量(这是它们的词汇的全部点:).