有没有办法使用常量作为哈希键?
例如:
use constant X => 1;
my %x = (X => 'X');
上面的代码将创建一个以“X”作为键而不是 1 作为键的散列。然而,我想使用常量 X 的值作为键。
use constant
实际上制作了常量子程序。
要执行您想要的操作,您需要显式调用 sub:
use constant X => 1;
my %x = ( &X => 'X');
或者
use constant X => 1;
my %x = ( X() => 'X');
另一种选择是不使用 use constant pragma 并按照 Damian Conway 的 Perl Best Practices 中的建议翻转到 Readonly。
在意识到常量哈希引用只是对哈希的常量引用后,我切换了一段时间,但不对哈希内的数据做任何事情。
readonly 语法会创建“正常外观”的变量,但实际上会强制保持不变性或只读性。您可以像使用任何其他变量一样使用它作为键。
use Readonly;
Readonly my $CONSTANT => 'Some value';
$hash{$CONSTANT} = 1;
您的问题是 => 是一个神奇的逗号,它会自动引用它前面的单词。所以你写的相当于('X','X')。
最简单的方法是只使用逗号:
my %x = (X, 'X');
或者,您可以添加各种标点符号,以便在 => 前面不再有一个简单的单词:
my %x = ( X() => 'X' );
my %x = ( &X => 'X' );
使用$hash{CONSTANT()}
或$hash{+CONSTANT}
防止裸词引用机制启动。
来自: http: //perldoc.perl.org/constant.html
大多数其他人都很好地回答了你的问题。总而言之,这些内容对问题和推荐的解决方法提供了非常完整的解释。问题是 Perl 编译指示“使用常量”确实在您当前的包中创建了一个子例程,其名称是编译指示的第一个参数,其值是最后一个。
在 Perl 中,一旦声明了子例程,就可以在没有括号的情况下调用它。
理解“常量”只是子例程,您可以看到为什么它们没有插入到字符串中,以及为什么引用左侧参数的“胖逗号”运算符“=>”认为你已经给它一个字符串(尝试其他内置-in 函数,如 time() 和 keys() 有时会加上逗号以获得额外的乐趣)。
幸运的是,您可以使用显式标点符号(如括号或 & 符号)来调用常量。
但是,我有一个问题要问您:您为什么要使用常量作为哈希键?
我可以想到一些可能会引导您朝这个方向发展的场景:
您想要控制哪些键可以在散列中。
您想抽象键的名称以防以后更改
在数字 1 的情况下,常量可能不会保存您的哈希值。相反,请考虑创建一个具有公共 setter 和 getter 的类,它们填充仅对对象可见的散列。这是一个非常不像 Perl 的解决方案,但很容易做到。
就第 2 种情况而言,我仍然强烈主张建立一个班级。如果对哈希的访问是通过定义良好的接口进行管理的,那么只有类的实现者负责正确获取哈希键名。在这种情况下,我根本不建议使用常量。
希望这会有所帮助,并感谢您的宝贵时间。
pragma 创建了一个子例程原型,use constant
不接受任何参数。虽然它看起来像一个 C 风格的常量,但它实际上是一个返回常量值的子例程。
如果=>
(fat comma) 是裸字,则 (fat comma) 会自动引用左操作数,$hash{key} 表示法也是如此。
如果您对常量名称的使用看起来像一个裸词,那么引用机制将启动,您将获得它的名称作为键而不是它的值。为防止这种情况发生,请更改用法,使其不是裸词。例如:
use constant X => 1;
%hash = (X() => 1);
%hash = (+X => 1);
$hash{X()} = 1;
$hash{+X} = 1;
在初始化程序中,您也可以使用普通逗号代替:
%hash = (X, 1);
=> 运算符将其左侧解释为“字符串”,就像 qw() 一样。
尝试使用
my %x = ( X, 'X');
一种方法是将 X 封装为 (X):
my %x ( (X) => 1 );
另一种选择是取消 '=>' 并使用 ',' 代替:
my %x ( X, 1 );
评论@shelfoo(声誉还不够高,无法直接在那里添加评论!)
完全同意 Damian Conway 的 Perl Best Practices ……强烈推荐阅读。
但是,如果您打算将 PBP 用作内部风格指南,请阅读PBP 模块推荐评论,这是一个有用的“勘误表”。