【问题标题】:Perl: constants and compile-time vs runtime hash lookups?Perl:常量和编译时与运行时哈希查找?
【发布时间】:2018-07-27 05:50:20
【问题描述】:

在 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.

这表示STATE_1 中的$fsm{STATE_2}->(@_); 行未定义。事实上,在这条线第一次出现的时候,STATE_2 函数还没有定义,但我指望在运行时解决哈希查找。

如果我将$fsm{STATE_2}->(@_); 替换为my $tmp = STATE_2; $fsm{$tmp}->(@_);,那么它会按预期工作,这看起来很老套。

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

【问题讨论】:

  • use Const::Fast; const my $STATE_1 => 1; 似乎合适?你也可以用它声明数组、哈希(以及它们的引用)。
  • 也许吧,不过我想避免添加使分发复杂化的外部依赖项。
  • 我认为你的状态应该是字符串。使用整数作为哈希键有点奇怪。只需删除 constant 定义并引用州名即可。
  • 是的,这绝对是我的 C 背景,希望我使用定义明确的常量作为标识符...
  • @John:字符串也是定义明确的常量。不同的是C没有哈希结构!

标签: perl hash constants


【解决方案1】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-31
    • 1970-01-01
    • 2013-01-23
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 2014-09-03
    • 1970-01-01
    相关资源
    最近更新 更多