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

Joh*_*aye 4 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}->();
Run Code Online (Sandbox Code Playgroud)

请注意STATE_1,我正在尝试调用该STATE_2函数.

但是,在运行时我得到这个:

Can't use an undefined value as a subroutine reference at ./self-reference-hash.pl line 15.
Run Code Online (Sandbox Code Playgroud)

这表示该$fsm{STATE_2}->(@_);STATE_1未定义.事实上,在这条线第一次出现的时候,该STATE_2功能没有定义还没有,但我对哈希查询计数在运行时得到解决.

如果我替换$fsm{STATE_2}->(@_);my $tmp = STATE_2; $fsm{$tmp}->(@_);然后它按预期工作,这似乎是hacky.

有更清洁的方法吗?

Joh*_*aye 13

这个问题的根源实际上是在Perl的doc中constant解释,它不是关于运行时与编译时的关系,而是关于Perl在某些情况下神奇地引用了裸字:

如果在自动引用裸字的上下文中使用常量,则可能会遇到麻烦(对于任何子例程调用都是如此).例如,你不能说$hash{CONSTANT}因为CONSTANT将被解释为一个字符串.使用$hash{CONSTANT()}$hash{+CONSTANT}防止裸字引用机制被踢入.同样,由于=>运算符立即向其左侧引用一个裸字,您必须说CONSTANT() => 'value'(或者仅使用逗号代替大箭头)而不是CONSTANT => 'value'.

列出的变通方法可以解决此问题.