【问题标题】:Why is my hash getting flattened?为什么我的哈希变平了?
【发布时间】:2018-03-21 00:34:44
【问题描述】:

我通过引用一个子例程来传递一个引用数组。当我尝试在子例程中尊重它时,它会给出一个扁平的哈希值。我怎样才能解决这个问题?我不想要一个平面哈希,我无法确定原因。

我确定我在某个地方犯了错误,但无法发现它。任何cmets /建议都完全欢迎!期待听到这个精彩社区的消息!提前致谢。

更新的问题陈述: 基本上我希望通过引用子例程来传递哈希。我的问题是,当我在带有标量变量的子例程中接受它,然后我尝试用 % 符号取消引用它时,我仍然得到一个平面哈希。

更新: 出现了混乱。当我检查我的哈希值是否平坦时,我只检查了print Dumper %hash,而实际上我应该实际检查与print Dumper \%hash。缺少这条信息导致了这个问题。

脚本:

#!/usr/bin/perl

use strict ;
use warnings ;
use Data::Dumper ;

my %h = (moe => "joe", toe => "poe") ;
my @a = (1,2,3,4) ;

my @refs = \(%h,@a) ;

sub sample()
{
  my $ref = shift ;
  my @refs = @{$ref} ;
  print "What I got in the sub! Seems OK!!\n" ;
  print Dumper @refs, "\n" ;

  my %h = %{$refs[0]} ;
  my @a = @{$refs[1]} ;

  print "I am not able to dereference this :(. Please help!! Hash is flat :(\n" ;
  print Dumper %h ;
  print Dumper @a ;
}

&sample(\@refs) ;

输出:

23:34:17[Host@User]$ ./test.pl 
What I got in the sub! Seems OK!!
$VAR1 = {
          'moe' => 'joe',
          'toe' => 'poe'
        };
$VAR2 = [
          1,
          2,
          3,
          4
        ];
$VAR3 = '
';
I am not able to dereference this :(. Please help!! Hash is flat :(
$VAR1 = 'moe';
$VAR2 = 'joe';
$VAR3 = 'toe';
$VAR4 = 'poe';
$VAR1 = 1;
$VAR2 = 2;
$VAR3 = 3;
$VAR4 = 4;

【问题讨论】:

  • 您可能喜欢 Data::Printer。如果是检查数据结构,它会比用于机器消耗的 Data::Dumper 更容易使用。
  • 你自己把事情弄得很复杂。您有大量的引用和取消引用,并且您滥用子例程原型并通过调用& 来击败它们。我只能想象这已被写成“查找所有错误”的家庭作业。这很好,但请在你的问题中这样说。
  • @simbabque:我一直不明白Data::Printer的吸引力,你能解释一下吗?我一直更喜欢Data::Dump 的输出而不是Data::Dumper 的输出,但这只是因为它的默认输出更简洁。还有JSONYAML 的选项,我不明白为什么另一种无法解析的格式比其中任何一种都好。
  • @Borodin 我喜欢它,因为它对哈希键进行排序,简洁明了地显示所有内容,了解类内部结构、继承、列出方法,而且它是彩色的!我用 Data::Dumper 学习了“调试”并使用了很长时间。我只是觉得当我必须阅读它时,p 更好。也许这是一种偏好,我不确定。但是你提到的其他都是用于传输数据的。 DDP 是为您快速阅读而设计的。
  • @Borodin 只要我们不需要在它周围加上<pre>,我对大多数人都很好。无论什么可用,都能完成工作。 :-)

标签: perl hash reference dereference


【解决方案1】:

没有什么可以解决的。你有你想要的。 %h 中有一个散列,@a 中有一个数组。

但是Data::Dumper 需要一个参数列表,并将其每个参数视为一个单独的变量来转储。因此,当您将散列或数组传递给 Dumper() 时,它们将展开到列表中,并且您会将它们显示为单独的变量。

如果您想使用Dumper() 查看数组或散列的结构,您应该传入对数据结构的引用。

print Dumper \%h;
print Dumper \@a;

当然,这实际上是您第一次致电Dumper() 时所做的。

print Dumper @refs;

我还应该指出,您的代码中有几个错误(幸运的是?)相互抵消。您使用空原型 (sample() { ... }) 定义子例程 sample,这意味着如果您向其传递任何参数,您将收到致命错误。但是当您调用子例程时,您会使用 & (&sample(@refs)),其效果之一是关闭原型检查 - 因此即使您将参数传递给子例程,它也可以工作。

最好完全省略原型 (sub sample { ... }) 并调用不带 & 符号的子例程 (sample(@refs)))。

【讨论】:

  • 嗨,我不使用原型的原因,正如我所提到的 - 我已经阅读了关于这方面的混合信息,所以我仍然不清楚并寻找更好的解释。我使用 & 符号,这样我就不会收到 sub 已被提前调用的警告(当使用警告时)。
  • 谢谢。我接受您的解释作为解决方案/答案。
  • @User9102d82:询问任何 Perl 专家是否应该使用原型,您会得到“不”的答案。使用它们有几个很好的理由,但它们都不适用于像您这样的简单代码。购买我的观点是您错误地使用它们。您正在声明一个带有空原型的子例程(这意味着“此子例程没有参数”),但您想将参数传递给子例程。这是你最大的问题。
  • @User9102d82:只要在调用上加上括号,就不会过早调用子程序的错误。像sample(@refs) 这样的调用总是可以正常工作,并且对于非 Perl 程序员来说看起来比&sample(@refs) 更容易识别。此外,将 & 号放在调用上关闭原型检查,如果您使用原型,这似乎是一件愚蠢的事情。
猜你喜欢
  • 1970-01-01
  • 2015-04-29
  • 2011-01-11
  • 1970-01-01
  • 2017-01-15
  • 1970-01-01
  • 1970-01-01
  • 2010-10-11
  • 1970-01-01
相关资源
最近更新 更多