在Perl 5.26中,基于常量的哈希查找似乎是在编译时而不是运行时解析的。如何强制在运行时解决它?
考虑以下简化的测试用例,该用例是从我尝试编写的基于哈希的状态机中构造出来的,其中键是状态标识符,值是状态函数。
use constant {
STATE_1 => 1,
STATE_2 => 2,
};
my %fsm;
%fsm = (
STATE_1, sub {
$fsm{STATE_2}->(@_);
return STATE_2;
},
STATE_2, sub {
return STATE_1;
}
);
my $state = STATE_1;
$state = $fsm{$state}->();
请注意,在STATE_1
中,我试图调用STATE_2
函数。
但是,在运行时我得到了:
Can't use an undefined value as a subroutine reference at ./self-reference-hash.pl line 15.
这表示$fsm{STATE_2}->(@_);
中的STATE_1
行未定义。确实,在此行第一次出现时,还没有定义STATE_2
函数,但我指望在运行时解析哈希查找。
如果我将$fsm{STATE_2}->(@_);
替换为my $tmp = STATE_2; $fsm{$tmp}->(@_);
,则它可以按预期运行,这似乎很麻烦。
是否有一种更清洁的方法?
答案 0 :(得分:13)
这个问题的根源实际上是在Perl's doc about constant
中进行了说明,它与运行时和编译时无关,而与Perl在某些情况下神奇地引用裸字有关:
如果在上下文中使用常量会遇到麻烦 自动引用裸字(对于任何子例程调用都是如此)。 例如,您不能说
$hash{CONSTANT}
,因为CONSTANT
将是 使用$hash{CONSTANT()}
或$hash{+CONSTANT}
来解释为字符串。 防止裸字引号机制启动。类似地, 由于=>运算符会在其左侧立即引用一个裸字,因此您 必须说CONSTANT() => 'value'
(或简单地用逗号代替 大箭头),而不是CONSTANT => 'value'
。
列出的解决方法解决了这个问题。