有没有办法使用“常量”? 作为 Perl 中的哈希键?

发布于 2024-07-06 16:04:43 字数 170 浏览 4 评论 0原文

有没有办法使用常量作为哈希键?

例如:

use constant X => 1;

my %x = (X => 'X');

上面的代码将创建一个以“X”作为键而不是 1 作为键的哈希。 然而,我想使用常量 X 的值作为键。

Is there any way to use a constant as a hash key?

For example:

use constant X => 1;

my %x = (X => 'X');

The above code will create a hash with "X" as key and not 1 as key. Whereas, I want to use the value of constant X as key.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

帅气称霸 2024-07-13 16:04:43

use Constant 实际上创建了常量子例程。

要执行您想要的操作,您需要显式调用 sub:

use constant X => 1;

my %x = ( &X => 'X');

use constant X => 1;

my %x = ( X() => 'X');

use constant actually makes constant subroutines.

To do what you want, you need to explicitly call the sub:

use constant X => 1;

my %x = ( &X => 'X');

or

use constant X => 1;

my %x = ( X() => 'X');
爱给你人给你 2024-07-13 16:04:43

另一种选择是不使用 use Constant pragma 并按照 Damian Conway 的 Perl 最佳实践中的建议切换到 Readonly。

在意识到常量哈希引用只是对哈希的常量引用之后,我切换了一段时间,但不对哈希内的数据执行任何操作。

只读语法创建“看起来正常”的变量,但实际上会强制执行恒定性或只读性。 您可以像使用任何其他变量一样使用它作为键。


use Readonly;

Readonly my $CONSTANT => 'Some value';

$hash{$CONSTANT} = 1;

Another option is to not use the use constant pragma and flip to Readonly as per recommendations in the Perl Best Practices by Damian Conway.

I switched a while back after realizing that constant hash ref's are just a constant reference to the hash, but don't do anything about the data inside the hash.

The readonly syntax creates "normal looking" variables, but will actually enforce the constantness or readonlyness. You can use it just like you would any other variable as a key.


use Readonly;

Readonly my $CONSTANT => 'Some value';

$hash{$CONSTANT} = 1;

夏见 2024-07-13 16:04:43

你的问题是 => 是一个神奇的逗号,会自动引用它前面的单词。 所以你写的相当于('X', 'X')。

最简单的方法就是只使用逗号:

my %x = (X, 'X');

或者,您可以添加各种标点符号,这样 => 前面就不再有一个简单的单词:

my %x = ( X() => 'X' );
my %x = ( &X => 'X' );

Your problem is that => is a magic comma that automatically quotes the word in front of it. So what you wrote is equivalent to ('X', 'X').

The simplest way is to just use a comma:

my %x = (X, 'X');

Or, you can add various punctuation so that you no longer have a simple word in front of the =>:

my %x = ( X() => 'X' );
my %x = ( &X => 'X' );
ぇ气 2024-07-13 16:04:43

使用 $hash{CONSTANT()}$hash{+CONSTANT} 来防止裸字引用机制启动。

来自:http://perldoc.perl.org/constant.html

Use $hash{CONSTANT()} or $hash{+CONSTANT} to prevent the bareword quoting mechanism from kicking in.

From: http://perldoc.perl.org/constant.html

怪我入戏太深 2024-07-13 16:04:43

其他大多数人都很好地回答了你的问题。 总而言之,这些内容对问题进行了非常完整的解释并推荐了解决方法。 问题是 Perl 编译指示“使用常量”实际上在当前包中创建了一个子例程,其名称是编译指示的第一个参数,其值是最后一个。

在 Perl 中,一旦声明了子例程,就可以在没有括号的情况下调用它。

了解“常量”只是子例程,您就可以明白为什么它们不在字符串中插入,以及为什么“胖逗号”运算符“=>” 它引用左侧参数认为您已经向它传递了一个字符串(尝试其他内置函数,例如 time() 和 keys() 有时使用粗逗号以获得​​额外的乐趣)。

幸运的是,您可以使用显式标点符号(例如括号或与符号)来调用常量。

但是,我有一个问题要问您:为什么要使用哈希键常量?

我可以想到一些可能引导您朝这个方向发展的场景:

  1. 您希望控制哪些键可以位于哈希中。

  2. 您想要抽象键的名称,以防以后发生变化

在第 1 种情况下,常量可能不会保存您的哈希值。 相反,请考虑创建一个具有公共 setter 和 getter 的类,用于填充仅对对象可见的哈希。 这是一个非常不像 Perl 的解决方案,但很容易做到。

就第二种情况而言,我仍然强烈主张建立一个班级。 如果通过定义良好的接口来管理对哈希的访问,则只有类的实现者负责获取正确的哈希键名称。 在这种情况下,我根本不建议使用常量。

希望这对您有所帮助,并感谢您的宝贵时间。

Most of the other folks have answered your question well. Taken together, these create a very full explanation of the problem and recommended workarounds. The issue is that the Perl pragma "use constant" really creates a subroutine in your current package whose name is the the first argument of the pragma and whose value is the last.

In Perl, once a subroutine is declared, it may be called without parens.

Understanding that "constants" are simply subroutines, you can see why they are not interpolated in strings and why the "fat comma" operator "=>" which quotes the left-hand argument thinks you've handed it a string (try other built-in functions like time() and keys() sometime with the fat comma for extra fun).

Luckily, you may invoke the constant using explicit punctuation like parens or the ampersand sigil.

However, I've got a question for you: why are you using constants for hash keys at all?

I can think of a few scenarios that might lead you in this direction:

  1. You want control over which keys can be in the hash.

  2. You want to abstract the name of the keys in case these change later

In the case of number 1, constants probably won't save your hash. Instead, consider creating an Class that has public setters and getters that populate a hash visible only to the object. This is a very un-Perl like solution, but very easily to do.

In the case of number 2, I'd still advocate strongly for a Class. If access to the hash is regulated through a well-defined interface, only the implementer of the class is responsible for getting the hash key names right. In which case, I wouldn't suggest using constants at all.

Hope this helps and thanks for your time.

软糯酥胸 2024-07-13 16:04:43

use Constant 编译指示创建一个原型为不带参数的子例程。 虽然它看起来像一个C 风格常量,但它实际上是一个返回常量值的子例程。

如果左操作数是裸字,则 =>(粗逗号)会自动引用左操作数,$hash{key} 表示法也是如此。

如果您使用的常量名称看起来像一个裸字,则引用机制将启动,您将得到它的名称作为键而不是它的值。 为了防止这种情况,请更改用法,使其不再是裸字。 例如:

use constant X => 1;
%hash = (X() => 1);
%hash = (+X => 1);
$hash{X()} = 1;
$hash{+X} = 1;

在初始化程序中,您还可以使用普通逗号代替:

%hash = (X, 1);

The use constant pragma creates a subroutine prototyped to take no arguments. While it looks like a C-style constant, it's really a subroutine that returns a constant value.

The => (fat comma) automatically quotes left operand if its a bareword, as does the $hash{key} notation.

If your use of the constant name looks like a bareword, the quoting mechanisms will kick in and you'll get its name as the key instead of its value. To prevent this, change the usage so that it's not a bareword. For example:

use constant X => 1;
%hash = (X() => 1);
%hash = (+X => 1);
$hash{X()} = 1;
$hash{+X} = 1;

In initializers, you could also use the plain comma instead:

%hash = (X, 1);
小镇女孩 2024-07-13 16:04:43

=> 运算符将其左侧解释为“字符串”,就像 qw() 那样。

尝试使用

my %x = ( X, 'X');

=> operator interprets its left side as a "string", the way qw() does.

Try using

my %x = ( X, 'X');
浪菊怪哟 2024-07-13 16:04:43

一种方法是将 X 封装为 (X):

my %x ( (X) => 1 );

另一种选择是取消“=>” 并使用 ',' 代替:

my %x ( X, 1 );

One way is to encapsulate X as (X):

my %x ( (X) => 1 );

Another option is to do away with '=>' and use ',' instead:

my %x ( X, 1 );
小情绪 2024-07-13 16:04:43

评论@shelfoo(声誉还不够高,无法直接在此处添加评论!)

完全同意 Damian Conway 的 Perl 最佳实践...强烈推荐阅读。

不过,请阅读PBP 模块推荐评论,如果您计划使用 PBP 作为内部风格指南。

Comment @shelfoo (reputation not high enough to add comment directly there yet!)

Totally agree about Perl Best Practices by Damian Conway... its highly recommended reading.

However please read PBP Module Recommendation Commentary which is a useful "errata" if you plan to use PBP for an in-house style guide.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文