On 12/5/06, Ken Williams <[EMAIL PROTECTED]> wrote:
>
> On Dec 4, 2006, at 12:35 PM, Julian Mehnle wrote:
>
> > Is it likely that this occurs with CPANTS in the first place?
> > Unfortuna-
> > tely, CPANTS doesn't tell the Data::Dumper version it is using... :-(
>
> I looked at the three failure reports you referenced, and seeing as 2
> of them come from the same person, perhaps we could ask imacat what
> version is installed?  I just used 'svn annotate' to go *way* back in
> the sources for M::B and I confirmed that we've been using "Terse"
> dumping since this feature was introduced.
>
> Another idea I just had by looking at the Data::Dumper docs was that
> maybe some funny refs are in the structure it's trying to write?  It
> says "$VARn names will be avoided where possible", and maybe in this
> case it doesn't think it's possible.  So we'd probably also need to
> see the build_params file to diagnose that.

Im shocked that anyone is using Terse in production code. It is
completely unsafe and intended ONLY for debugging purposes. In fact id
say that using Data::Dumper without Purity(1) as a serialization
mechanism in production code is simply insane.

All you need is a single ref in two positions in a data structure to
make an unevalable dump without Purity(1). With Terse it will just be
worse.

Note only the last dump is actually valid.

d:\sync-clone>perl -MData::Dumper -le"my $x=[]; my $y=[$x,$x]; print
Dumper($y); print Data::Dumper->new([$y])->Terse(1)->Dump; print
Data::Dumper->new([$y])->P
urity(1)->Dump();
$VAR1 = [
          [],
          $VAR1->[0]
        ];

[
          [],
          $VAR1->[0]
        ]

$VAR1 = [
          [],
          []
        ];
$VAR1->[1] = $VAR1->[0];


So it looks like two issues, first, using Dumper in production code
without Purity(1), and second, somehow the data structure being dumped
contains a duplicated reference.

This is the reason why in DDS the default is Purity(1), even tho in
debugging it makes the dump harder to read. You have to specifically
request an unsafe mode for output. With Dumper it gives an unsafe
output by default and you have to request the safe mode explicitly.

The proper way to get DD to do what I think you want to do is as follows:

my $serialized="do{ my "
                      . Data::Dumper->new([$var],['dumped_var'])
                                           ->Purity(1)
                                           ->Dump()
                      . '$dumped_var }';

and then later on you do:

my $deserialized=eval $serialized or die "Error '$@' in serialized
code:\n$serialized";

By putting the code in a do{} block, adding the my, explicitly
designating the variable name it will use and explicitly asking the
do{} to return the correct value you get the same effect as Terse()
but it is actually robust.

Of course you can waste a lot of time working out why the ref occurs
in the original data structure multiple times, but well, why bother?
Just serialize it properly.

Cheers,
Yves

-- 
perl -Mre=debug -e "/just|another|perl|hacker/"

Reply via email to