Re: Data::Dumper scalar refs undef
by demerphq (Chancellor) on Sep 23, 2003 at 10:16 UTC
|
This is a well known problem with Data::Dumper. Whether it gets these things right is a matter of the order the values occur in. There are two problems involved in your example. The first is that Data::Dumper does a depth first traversal of the data structure. However in this case this is a trivial aspect. The second and in this case critical factor is that Data::Dumper does a single pass over the data structure and as such can't determine ahead of time that the thing that is referenced by $a->[0] is actually the scalar in $hash->{type}. The problem could be worked around by having Data::Dumper use the Array::RefElem module to make $hash->{$type} an alias to ${$array->[0]}
and then it would all work out. Actually I have worked on a patch for Data::Dumper to do this, probably I'll pick it up again.
Suffice it to say that DD is not suitable for data structures that are self referential _and_ where those references involve references to scalars that are part of composite objects like hashes or arrays which it also has to dump, even in Purity mode. It simply cannot tell the difference between a reference to an element and a reference to an anoymous scalar, and doesnt know how to fix the problem once it has come up. If you want that then use Storable. Or you could have a whirl with the extremely alpha (and due for a total rewrite Real Soon Now) Data::BFDump. Unfortunately the later has problem on other platforms not to mention a few buggy areas. There is also Data::XDumper which I understand is quite good, but i've not had a look at it recently. AFAIK, YAML and Data::Dump are completely unsuited to this type of data structure, but they too may have moved on since I last time I tested them on cases like this. (YAML advertises that it cannot handle my $x; $x=\$x; at all, which Data::Dumper has no problem with under Purity. Data::Dump when I last checked could be induced to infinte recurse by the correctly chosen data structure)
The first record of this in Perl lore that I know of is by merlyn, and I mentioned it here a while back (a few times, do super search fo DD and my name, theres lots of stuff there :-) . Its been my on and off project for some time to produce a dumper that can handle these things better than DD, but lately its been a whole lot more off than on. :-(
HTH
---
demerphq
Everybody remember the Gandhi quote?
First they ignore you, then they laugh at you, then they fight you, then you win.
Gentlemen and ladies, this newest leaked memo from Microsoft confirms that we are advancing through GandhiCon Three.
| [reply] [d/l] [select] |
|
|
ysh -r
Welcome to the YAML Test Shell. Type ':help' for more information.
ysh > $a = { type => 'int' };
--- #YAML:1.0
type: int
ysh > $b = \$a->{type};
--- #YAML:1.0 !perl/ref:
=: int
ysh > [$b,$a]
--- #YAML:1.0
- !perl/ref:
=: int
- type: !perl/ref:
=: int
ysh > $$b={hi=>'there'}
--- #YAML:1.0
hi: there
ysh > [$b,$a]
--- #YAML:1.0
- !perl/ref:
=: &1
hi: there
- type: *1
Update: I'm not so sure. That !perl/ref: disappears
Ah. Perhaps b/c a hash is assumed to be a reference in YAML. | [reply] [d/l] |
Re: Data::Dumper scalar refs undef
by Roger (Parson) on Sep 23, 2003 at 12:23 UTC
|
You NEED to use the extended version of the dumper to do self referencing dump.
#!perl -w
use Data::Dumper;
$Data::Dumper::Purity=1;
$a = { type => 'int' };
$b = \$a->{type};
print "case 1\n", Data::Dumper->Dump([$a, $b], [qw/a b/]);
print "case 2\n", Data::Dumper->Dump([$a, $b], [qw/x y/]);
print "case 3\n", Data::Dumper->Dump([$b, $a], [qw/b a/]);
print "case 4\n", Data::Dumper->Dump([$b, $a]);
This gives you the following output:
case 1
$a = {
'type' => 'int'
};
$b = \$a->{'type'};
case 2
$x = {
'type' => 'int'
};
$y = \$x->{'type'};
case 3
$b = \'int';
$a = {
'type' => ${$b}
};
case 4
$VAR1 = \'int';
$VAR2 = {
'type' => ${$VAR1}
};
In other words, Data::Dumper is smart, but not 'that' smart. In case of dumping variables referencing each other, you have to use the extended Dump and optionally give it the names of your variables so it can distinguish them properly.
Case 3 and 4 are special, they do not match exactly the original input variables. This is caused by the Data::Dumper's parser. The parser maintains a symbolic table of all variables seen, and for every new variable, it will search in the table first. If a match was found, then it would interpret the new variable based on the matching variable in the table. Therefore the ordering of the variables is important, just like defining them in perl script. | [reply] [d/l] [select] |
|
|
Case three and four is wrong. Naming changing nothing about this. What you can do, is register _specific_ references as having a name, _and_ name the root objects. However this is not feasable unless you know what these references are ahead of time. For a different and IMO clearer example of this problem try the following:
Dumper version: 2.102
----------------------------------------
Before:
$VAR1 = [
\\do{my $o},
do{my $o}
];
${${$VAR1->[0]}} = $VAR1->[0];
$VAR1->[1] = ${$VAR1->[0]};
After:
$VAR1 = [
\\do{my $o},
do{my $o}
];
${${$VAR1->[0]}} = $VAR1->[0];
$VAR1->[1] = ${$VAR1->[0]};
$dump and $after are the same as each other
Before:
$VAR1 = [
\\do{my $o},
do{my $o}
];
${${$VAR1->[0]}} = $VAR1->[0];
$VAR1->[1] = ${$VAR1->[0]};
After:
$VAR1 = [
\\do{my $o},
do{my $o}
];
${${$VAR1->[0]}} = $VAR1->[0];
$VAR1->[1] = ${$VAR1->[0]};
$dump and $after are the same as each other
Before:
$VAR1 = [
\\do{my $o},
do{my $o}
];
${${$VAR1->[0]}} = $VAR1->[0];
$VAR1->[1] = ${$VAR1->[0]};
After:
$VAR1 = [
\\do{my $o},
do{my $o}
];
${${$VAR1->[0]}} = $VAR1->[0];
$VAR1->[1] = ${$VAR1->[0]};
$dump and $after are the same as each other
----------------------------------------
$VAR1 = [
\'Test',
'Test'
];
$VAR1 = [
\'Test',
${$VAR1->[0]}
];
$VAR1 = [
\'Test',
${$VAR1->[0]}
];
---
demerphq
First they ignore you, then they laugh at you, then they fight you, then you win.
-- Gandhi
• Update:
*blush* the before and after was wrong. Still my point is clear. These data structures are different, but dump the same.
| [reply] [d/l] [select] |
Re: Data::Dumper scalar refs undef
by BrowserUk (Patriarch) on Sep 23, 2003 at 09:59 UTC
|
When dumping self-referential structures, you need to enable $Data::Dumper::Purity = 1;
See the pod for the explaination.
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
If I understand your problem, I can solve it! Of course, the same can be said for you.
| [reply] [d/l] |
|
|
| [reply] |
|
|
| [reply] |
Re: Data::Dumper scalar refs undef
by qmole (Beadle) on Sep 23, 2003 at 08:40 UTC
|
Change $b = \$a->{type}; to:
$b = $a->{type};
Sorry, misread the question.
| [reply] [d/l] [select] |
|
|
But then $b will just be a copy of $a->{type}, not a
scalar reference to it.
I use a reference so that if I change $b (or $$b),
that also changes $a->{type}
In the original context it may make more sense.
Or it may not.
I'm still in the midst of things there
Missed the strike-out by half a second...
| [reply] |