【问题标题】:Strict refs error when working with hash reference使用哈希引用时出现严格的引用错误
【发布时间】:2017-12-20 02:56:47
【问题描述】:

我将包含我已验证的代码来说明我的问题。我的目标是将此处模拟的数据库查询返回的哈希作为 %r (其中包含数字索引),并使用“名称”字段的值作为接收哈希中的键。 (此哈希将包含来自多个查询的结果。)

我觉得我很可能在引用和取消引用方面做了一些愚蠢的事情。我真的很想尝试在这里掌握工作中的概念。谢谢!

#!/usr/bin/perl -T

use strict;
use warnings;

my %hash;
my %r = (
  '1' => {
    name => 'Harry',
    desc => 'Prince',
  },
);

MergeHash(\%hash,\%r);
foreach my $name (keys %hash) {
  print "name = $name, desc = $hash{$name}{desc}\n"; # EDIT: REVISED
}
exit;

sub MergeHash {
  my $h = shift; # reference to receiving hash
  my $r = shift; # reference to giving hash
  foreach my $i (keys %{$r}) {
    $$h{name} = $$r{$i}{name} || 'Unknown'; # okay
    $$h{name}{desc} = $$r{$i}{desc} || 'Unknown'; # Can't use string ("Harry") as a HASH ref while "strict refs" in use at ./test.pl line 25.
  }
}

编辑:根据要求,输出(在上面的代码中也表示为 cmets):

Can't use string ("Harry") as a HASH ref while "strict refs" in use at ./test.pl line 25.

编辑#2:修改打印行(在上面的代码中)以明确 %hash 中所需的结构。

【问题讨论】:

    标签: perl reference dereference


    【解决方案1】:
    $$h{name}{desc}
    

    更清楚地写成

    $h->{name}{desc}
    

    简称

    $h->{name}->{desc}
    

    这样更清楚,$h->{name} 的值被用作哈希引用(就像之前的 $h 的值一样),但它包含一个字符串。


    您只需将name 替换为实际名称,因为这就是您想要的密钥。

    for my $i (keys(%$r)) {
        $h->{ $r->{$i}{name} }{desc} = $r->{$i}{desc};
    }
    

    我们实际上并不需要$i,所以让我们简化一下。

    for my $row (values(%$r)) {
        $h->{ $row->{name} }{desc} = $row->{desc};
    }
    

    上面的问题是,它不适合每行超过一个字段。以下处理更好:

    for my $row (values(%$r)) {
        $h->{ $row->{name} } = {
           desc => $row->{desc},
           # ...
        };
    }
    

    为什么要构建一个新的哈希值,而我们已经拥有的哈希值呢?

    for my $row (values(%$r)) {
        $h->{ $row->{name} } = $row;
    }
    

    【讨论】:

    • 我非常感兴趣地关注了您回答中的所有编辑。你答案中的最后一个 sn-p 完全符合我的期望。我想我什至明白为什么。起初我认为它很神奇,因为根本没有提到“desc”。但我认为它所做的是遍历哈希中的所有值,所以我不必将它单独列出。这实际上是我接下来要做的工作。我从你和 jeff6times7 那里学到了很多,非常感谢!
    • 请记住,哈希%$r 的值是对哈希的引用(例如{ name => 'Harry', desc => 'Prince', } 返回的引用,所以它正在执行$h->{ $row->{name} } = { name => 'Harry', desc => 'Prince', },异常使用相同的哈希而不是复制。
    【解决方案2】:

    如果你想用来自给定哈希的所有数据覆盖接收哈希的成员,那么下面的代码将起作用。

    sub MergeHash {
       my $h = shift; # reference to receiving hash
       my $r = shift; # reference to giving hash
       while (my ($k, $v) = each %$r) {
          $h->{$k} = $v;
       }
    }
    

    问题在于 $$h 假设 $h 是对 SCALAR 的引用,但它不是,它是对 HASH 的引用,您通常会看到人们要么取消引用哈希,一边引用它的成员,就像我所做的那样更多。另一种方法是像这样声明哈希的副本,但这不适用于您的用例:

    my %copyofh = %$h;
    

    【讨论】:

      猜你喜欢
      • 2014-07-27
      • 2021-09-23
      • 2017-04-08
      • 1970-01-01
      • 2019-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-11
      相关资源
      最近更新 更多