显示的问题是由于这些常量是裸字(在编译时构建的)
使用此模块定义的常量不能像变量一样插入到字符串中。
在current implemenation(constant pragma)中,它们是“inlinable
子程序”(参见†)。
使用Const::Fast这样的模块可以很好地解决这个问题
use Const::Fast;
const my $foo => 'FOO';
const my $bar => 'BAR';
my $var = 'prefix1_FOO_more';
$var =~ s/prefix1_$foo/prefix2_$bar/g;
现在它们确实被插值了。请注意,更复杂的替换可能需要/e。
这些是在运行时构建的,因此您可以将表达式的结果分配给它们。特别是可以使用qr operator,例如
const my $patt => qr/$foo/i; # case-insensitive
qr 是构建正则表达式模式的推荐方法。 (它是interpolates,除非分隔符是'。)性能提升通常很小,但你会得到一个适当的正则表达式,可以这样构建和使用(在这种情况下也是一个常量)。
我很容易推荐Const::Fast 模块而不是另一个模块,实际上目前是所有其他模块。请参阅recent article,详细讨论两者。这是review 的许多其他选项。
我强烈建议对只读的内容使用常量(您选择的类型)。这有利于代码的健康,以及与它接触的开发人员(包括众所周知的六个月内的开发人员)。
† 这些是子例程,我们需要能够运行代码,以便对它们进行评估和替换为给定值。不能只是“插值”(评估)一个变量——它不是一个变量。
run code inside a string(需要interpolated,因此有效地双引号)的一种方法是取消引用,其中引用下的块中有一个表达式;然后计算表达式。所以我们需要先做这个参考。所以要么
say "@{ [FOO] }"; # make array reference, then dereference
或
say "${ \FOO }"; # make scalar reference then dereference
打印foo。请参阅文档以了解其工作原理和示例。因此,人们可以在正则表达式中做同样的事情,无论是在匹配部分还是替换部分中
s/prefix1_${\FOO}/prefix2_${\BAR}/g;
(或@{[...]}),因为它们被评估为插值字符串。
哪个“更好”?这些都是技巧。很少(如果有的话)需要这样做。它有很好的机会迷惑读者。所以我根本不建议使用这些。
至于(?{ code }),这是一个正则表达式功能,代码在模式内进行评估(仅匹配端)。它既复杂又棘手,而且很少需要。请参阅 in perlretut 和 in perlre。
讨论这些事情的速度并不重要。它们肯定超出了干净和惯用代码的范围,而您很难检测到运行时差异。
但如果您必须使用其中之一,我宁愿通过技巧在标量引用中进行插值,然后使用复杂的正则表达式功能。