有没有办法将常量用作散列键?
例如:
use constant X => 1;
my %x = (X => 'X');
上面的代码将创建一个散列,其中“X”作为键,而不是1作为键。然而,我想使用常数X的值作为关键。
答案 0 :(得分:45)
use constant
实际上是常量子程序。
要做你想做的事,你需要明确地调用sub:
use constant X => 1;
my %x = ( &X => 'X');
或
use constant X => 1;
my %x = ( X() => 'X');
答案 1 :(得分:19)
根据Damian Conway的Perl最佳实践中的建议,另一个选择是不使用使用常量编译指示并翻转到Readonly。
我意识到常量散列引用只是对散列的一个常量引用,但我没有做任何关于散列内部数据的事情。
readonly语法创建“正常查看”变量,但实际上会强制执行常量或只读。您可以像使用任何其他变量一样使用它。
use Readonly;
Readonly my $CONSTANT => 'Some value';
$hash{$CONSTANT} = 1;
答案 2 :(得分:14)
你的问题是=>是一个魔术逗号,自动引用它前面的单词。所以你写的相当于('X','X')。
最简单的方法是使用逗号:
my %x = (X, 'X');
或者,您可以添加各种标点符号,以便在=>前面不再有简单的单词:
my %x = ( X() => 'X' );
my %x = ( &X => 'X' );
答案 3 :(得分:9)
使用$hash{CONSTANT()}
或$hash{+CONSTANT}
来防止裸字引用机制被踢入。
答案 4 :(得分:6)
其他大多数人都很好地回答了你的问题。总之,这些创建了对问题的完整解释和推荐的解决方法。问题是Perl pragma“use constant”确实在当前包中创建了一个子例程,其子名称是pragma的第一个参数,其值是最后一个。
在Perl中,一旦声明了子例程,就可以在没有parens的情况下调用它。
理解“常量”只是子程序,你可以看到它们没有用字符串插值的原因以及为什么“胖逗号”运算符“=>”引用左手参数认为你已经把它递给了一个字符串(尝试其他内置函数,比如time()和keys(),有时用胖逗号来获得额外的乐趣)。
幸运的是,您可以使用明显的标点符号来表示常量,例如parens或&符号。
但是,我有一个问题:你为什么要使用常量来表示哈希键呢?
我可以想到一些可能引导您朝这个方向发展的方案:
您希望控制哈希中的哪些键。
您希望抽象出密钥的名称,以防以后更改
在数字1的情况下,常量可能不会保存您的哈希值。相反,请考虑创建一个具有公共setter和getter的类,该类填充仅对该对象可见的哈希。这是一个非常不像Perl的解决方案,但很容易做到。
在2号的情况下,我仍然坚持主张一个班级。如果通过定义良好的接口来调节对散列的访问,则只有该类的实现者负责获取正确的散列键名称。在这种情况下,我不会建议使用常量。
希望这有助于并感谢您的时间。
答案 5 :(得分:5)
use constant
pragma创建一个子例程原型,不带参数。虽然看起来就像一个C风格的常量,但它实际上是一个返回常量值的子程序。
=>
(胖逗号)会自动引用左操作数,如果它是一个单词,就像$ hash {key}表示法一样。
如果您对常量名称的使用看起来像一个单词,引用机制将会启动,您将获得其名称作为键而不是其值。要防止这种情况,请更改用法,使其不是一个单词。例如:
use constant X => 1;
%hash = (X() => 1);
%hash = (+X => 1);
$hash{X()} = 1;
$hash{+X} = 1;
在初始值设定项中,您也可以使用普通逗号:
%hash = (X, 1);
答案 6 :(得分:2)
=>运算符将其左侧解释为“字符串”,qw()的方式。
尝试使用
my %x = ( X, 'X');
答案 7 :(得分:2)
一种方法是将X封装为(X):
my %x ( (X) => 1 );
另一种选择是取消'=>'并使用','代替:
my %x ( X, 1 );
答案 8 :(得分:1)
评论@shelfoo(声誉不足以直接在那里添加评论!)
完全同意达米安康威的Perl最佳实践......强烈推荐阅读。
但是,如果您计划将PBP用于内部样式指南,请阅读PBP Module Recommendation Commentary这是一个有用的“勘误表”。