首页 > 解决方案 > Perl:常量和编译时与运行时哈希查找?

问题描述

在 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}->(@_);then 它会按预期工作,这似乎很hacky。

有没有更清洁的方法来做到这一点?

标签: perlhashconstants

解决方案


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

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

列出的解决方法可解决该问题。


推荐阅读