Perl:常量和编译时与运行时哈希查找?

时间:2018-07-26 21:26:57

标签: perl hash constants

在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}->(@_);,则它可以按预期运行,这似乎很麻烦。

是否有一种更清洁的方法?

1 个答案:

答案 0 :(得分:13)

这个问题的根源实际上是在Perl's doc about constant中进行了说明,它与运行时和编译时无关,而与Perl在某些情况下神奇地引用裸字有关:

  

如果在上下文中使用常量会遇到麻烦   自动引用裸字(对于任何子例程调用都是如此)。   例如,您不能说$hash{CONSTANT},因为CONSTANT将是   使用$hash{CONSTANT()}$hash{+CONSTANT}来解释为字符串。   防止裸字引号机制启动。类似地,   由于=>运算符会在其左侧立即引用一个裸字,因此您   必须说CONSTANT() => 'value'(或简单地用逗号代替   大箭头),而不是CONSTANT => 'value'

列出的解决方法解决了这个问题。