1

我有几个引用彼此元素的嵌套数据结构。我希望能够检查这些引用,所以我正在寻找可以打印嵌套结构的内存地址的东西。一个选项Data::Dumper会很好。

以下是我的意思的一些例子:

my @a = ( [1,2,3], [4,5,6] );
print \@a;

会给你类似的东西:

ARRAY(0x20071dc8)

当您通过调试器运行相同的代码并使用x \@a它检查数组时,将打印以下内容:

0  ARRAY(0x20070668)
   0  ARRAY(0x2006c0d8)
      0  1
      1  2
      2  3
   1  ARRAY(0x2006c1b0)
      0  4
      1  5
      2  6

但是使用Data::Dumper

print Dumper \@a;

看起来像这样

$VAR1 = [
          [
            1,
            2,
            3
          ],
          [
            4,
            5,
            6
          ]
        ];

我真正想要的是Data::Dumper输出和调试器提供的细节的混合。或许这

$VAR1 = [ ARRAY(0x20070668)
          [ ARRAY(0x2006c0d8)
            1,
            2,
            3
          ],
          [ ARRAY(0x2006c1b0)
            4,
            5,
            6
          ]
        ];

编辑

考虑这段代码。输出没有解释$b[1]与中相同的参考$a[0]

use Data::Dumper;

my @a = ( [1,2,3], [4,5,6] );
my @b = ( ["a","b","c"], $a[0] );

print Dumper \@b

print $b[1], "\n";
print $a[0], "\n";

输出

$VAR1 = [
          [
            'a',
            'b',
            'c'
          ],
          [
            1,
            2,
            3
          ]
        ];


ARRAY(0x2002bcc0)
ARRAY(0x2002bcc0)

此外,当一个结构引用另一个结构的内容时,这种方法是否被认为是良好的编程实践?也许这是一个太笼统的问题,并且在很大程度上取决于特定的代码,但我想知道您的意见。

4

2 回答 2

4

Data::Dumper已经知道是否重用了引用。

在以下示例中,AoA 的第二个和第三个元素是相同的。这在 Dumper 输出中表示:

use strict;
use warnings;

my @array1 = (1..3);
my @array2 = (4..6);

my @AoA = (\@array1, \@array2, \@array2);

use Data::Dumper;
print Dumper \@AoA;

输出:

$VAR1 = [
          [
            1,
            2,
            3
          ],
          [
            4,
            5,
            6
          ],
          $VAR1->[1]
        ];

回应您的编辑

如果你想找到两个不同数据结构之间的关系,只需使用两个数据结构对 Dumper 进行一次调用。

您可以通过将它们作为列表或另一个匿名数据结构(如哈希或数组)中的值传递来做到这一点:

use strict;
use warnings;

my @a = ([1,2,3], [4,5,6]);
my @b = (["a","b","c"], $a[0]);

use Data::Dumper;

print Dumper(\@a, \@b);

输出:

$VAR1 = [
          [
            1,
            2,
            3
          ],
          [
            4,
            5,
            6
          ]
        ];
$VAR2 = [
          [
            'a',
            'b',
            'c'
          ],
          $VAR1->[0]
        ];
于 2014-08-11T19:32:20.703 回答
4

我认为对 . 的关注太少了Data::Dump。它由卓越LWP的模块套件的作者 Gisle Aas 编写。

在这种情况下,它将对您有所帮助,因为有一个配套Data::Dump::Filtered模块允许您提供回调以准确指示每个项目应如何在转储中显示。

该程序以您问题中的数据为例。它使用一个回调,在显示每个数组之前将引用的字符串化版本添加为 Perl 注释。eval转储与您的要求非常相似,作为奖励,它仍然是有效的 Perl 代码,如有必要可以通过。

请注意,所有转储输出都发送到,STDERR因此我已调用select STDERR以保持print输出与转储同步。

use strict;
use warnings;

use Data::Dump::Filtered qw/ dump_filtered /;

my @a = ( [1,2,3], [4,5,6] );
my @b = ( [ qw/ a b c / ], $a[0] );

select STDERR;

dump_filtered(\@a, \&filter);
print "\n";

dump_filtered(\@b, \&filter);
print "\n";

print '$b[1] is ', $b[1], "\n";
print '$a[0] is ', $a[0], "\n";

sub filter {
  my ($thing, $ref) = @_;
  return { comment => "$ref" } if $thing->is_array;
}

输出

# ARRAY(0x45179c)
[
  # ARRAY(0xa2d36c)
  [1, 2, 3],
  # ARRAY(0x44adc4)
  [4, 5, 6],
]

# ARRAY(0x4e6964)
[
  # ARRAY(0xa2d534)
  ["a", "b", "c"],
  # ARRAY(0xa2d36c)
  [1, 2, 3],
]

$b[1] is ARRAY(0xa2d36c)
$a[0] is ARRAY(0xa2d36c)
于 2014-08-11T21:35:57.053 回答