【问题标题】:Is it possible to have a hash of hashes (not hashrefs) in perl?是否可以在 perl 中有一个哈希值(不是 hashrefs)?
【发布时间】:2014-06-17 08:31:01
【问题描述】:

在 perl 中,可以使用哈希,例如my %a = (2, "two"); 以及 hashrefs,例如my $b = {2 => "two"};

每当我创建多维散列时,顶级散列的值始终是散列引用,即在它们上调用 ref() 会返回 "HASH"。是否有可能在没有额外间接级别的情况下拥有仅由哈希组成的哈希?

此外,当使用散列的散列时,perl 允许在访问子散列的元素时省略解引用运算符:

my %a;
$a{2} = {2 => "two"};

# the following are both valid:
$a{2}->{2}
$a{2}{2}

我假设第二个只是第一个的语法糖。但是,这似乎与简单的非嵌套 hashref 所需的语法不一致,因为 $b->{2} 有效,而 $b{2} 无效。

我问的原因是我想说

for my %hash (values %a) { 

甚至

for my %hash (map(%{$_}, values %a)) {

但这两种方法都会在编译时导致“循环变量上缺少 $”错误。

【问题讨论】:

  • 只回答标题:不,不可能。不过,您的问题值得更长、更有见地的答案。 . .
  • "for my %$hash (values %a) {" 应该在那里实现你的目标。
  • @Casao:不,那是错误的。 Perl 循环变量必须是标量
  • @Max Wallace,不。哈希和数组只能包含标量。
  • $b->{2} 不能缩写为 $b{2},因为它意味着别的东西。 $b{2}->{2} 可以缩写为 $b{2}{2},因为它没有任何意义。

标签: perl hash syntax multidimensional-array nested


【解决方案1】:

一开始,只有标量、散列和数组。实际上,那是 Perl4,但在设计 Perl5 时,绝对的向后兼容性是一个关键点。这意味着$hash{entry} = @array 必须继续将数组大小分配给该哈希条目,而不是将数组放入哈希中。所以集合只能包含标量。

这是需要 references 的主要原因之一——散列引用和数组引用允许我们将集合作为单个标量对象来引用。哈希引用的语法需要与哈希的语法不同。取消引用箭头->(借用自 C)可用于 hashref 访问:$hashref->{entry}。因为散列不能直接包含集合,下标之间的解引用箭头对于消除散列和散列引用之间的歧义是不必要的,所以$ref->{a}->{b}$ref->{a}{b} 做同样的事情。但是,hashref 访问不能使用 $ref{entry},因为该语法已用于哈希访问,因为 $name%name 可以作为单独的变量同时存在。

简而言之,语法很丑陋,但出于良好的向后兼容原因。

据我所知,目前不允许使用 for my %hash (@hash_references)for my @array (@hash_references)。我个人认为这种语法没有任何问题,但隐式取消引用无疑是相当令人困惑的。不得不使用%$ref 而不是%hash 并不是那么糟糕。

顺便说一句,Perl6 摆脱了引用,因为除了向后兼容性之外,哈希和 hashrefs 之间的这种差异是完全不必要的。集合变量的行为更像标量,尽管有一些新的上下文(如“项目上下文”)来帮助解决缺少引用的问题。

【讨论】:

    【解决方案2】:

    不,哈希值始终是标量。散列和数组不是标量,所以不能是散列值,但对它们的引用是标量,所以可以是散列值。

    perldata 文档页面的第一段说(我的重点):

    Perl 具有三种内置数据类型:标量、标量数组和关联数组标量,称为“哈希”。标量是单个字符串(任何大小,仅受可用内存限制)、数字或对某物的引用(将在 perlref 中讨论)。普通数组是按数字索引的标量的有序列表,从 0 开始。散列是按相关字符串键索引的标量值的无序集合。

    【讨论】:

      【解决方案3】:

      没有额外的间接级别,是否有可能只包含哈希值?

      没有。其他语言隐含地按照您的要求执行,但另一方面,它们没有可以在 perl 中找到的标量和列表上下文。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-02-09
        • 2011-05-19
        • 2011-09-30
        • 2012-08-10
        • 2013-06-23
        • 1970-01-01
        • 2014-03-22
        • 1970-01-01
        相关资源
        最近更新 更多