Reputation: 8042
I have several nested data structures that refer to one another's elements. I would like to be able to check those references, so I am searching for something that will print the memory address of nested structures. An option for Data::Dumper
would be fine.
Here are some examples of what I mean:
my @a = ( [1,2,3], [4,5,6] );
print \@a;
Will give you something like:
ARRAY(0x20071dc8)
When you run the same code through the debugger and examine the array with x \@a
it will print this:
0 ARRAY(0x20070668)
0 ARRAY(0x2006c0d8)
0 1
1 2
2 3
1 ARRAY(0x2006c1b0)
0 4
1 5
2 6
But using Data::Dumper
print Dumper \@a;
It looks like this
$VAR1 = [
[
1,
2,
3
],
[
4,
5,
6
]
];
What I really want is a mixture of the Data::Dumper
output and the details that the debugger provides. Perhaps this
$VAR1 = [ ARRAY(0x20070668)
[ ARRAY(0x2006c0d8)
1,
2,
3
],
[ ARRAY(0x2006c1b0)
4,
5,
6
]
];
Edit
Consider this code. The output doesn't explain that $b[1]
is the same reference as in $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";
output
$VAR1 = [
[
'a',
'b',
'c'
],
[
1,
2,
3
]
];
ARRAY(0x2002bcc0)
ARRAY(0x2002bcc0)
Also, is this approach, when one structure references the contents of another, considered to be good programming practice? Maybe this is too general question and heavily depends on particular code but I would like to know your opinion.
Upvotes: 1
Views: 868
Reputation: 126722
I believe that far too little attention is paid to Data::Dump
. It is written by Gisle Aas, the author of the remarkable LWP
suite of modules.
It will help you in this case because there is a companion Data::Dump::Filtered
module that allows you to supply a callback to dictate exactly how each item should be displayed in the dump.
This program takes the data in your question as an example. It employs a callback that adds the stringified version of the reference as a Perl comment before each array is displayed. The dump is very similar to your requirement, and as a bonus it is still valid Perl code that can be passed through eval
if necessary.
Note that all dump output is sent to STDERR
so I have called select STDERR
to keep the print
output in synch with the dumps.
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;
}
output
# 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)
Upvotes: 4
Reputation: 35198
Data::Dumper
will already tell if a reference is reused.
In the following example, the 2nd and 3rd elements of the AoA are identical. This is represented in the Dumper output:
use strict;
use warnings;
my @array1 = (1..3);
my @array2 = (4..6);
my @AoA = (\@array1, \@array2, \@array2);
use Data::Dumper;
print Dumper \@AoA;
Outputs:
$VAR1 = [
[
1,
2,
3
],
[
4,
5,
6
],
$VAR1->[1]
];
If you want to find the relation between two different data structures, just make a single call to Dumper with both data structures.
You can do this by passing them as a list, or as values in another anonymous data structure, like a hash or array:
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);
Outputs:
$VAR1 = [
[
1,
2,
3
],
[
4,
5,
6
]
];
$VAR2 = [
[
'a',
'b',
'c'
],
$VAR1->[0]
];
Upvotes: 4