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