develooper Front page | perl.perl5.porters | Postings from April 2001

[ID 20010427.003] Data::Dumper is hard to use reliably

Thread Next
From:
Andrew Pimlott
Date:
April 27, 2001 05:46
Subject:
[ID 20010427.003] Data::Dumper is hard to use reliably
Message ID:
E14sd8y-0004Cn-00@localhost
This is a bug report for perl from pimlott@idiomtech.com,
generated with the help of perlbug 1.28 running under perl v5.6.0.


-----------------------------------------------------------------
[Please enter your report here]

Data::Dumper is (needlessly?) difficult to use for serializing data
structures.  Since this is probably a primary use of Data::Dumper, it would
be nice to make it easier to do so reliably.

I'm referring mostly to the handling of self-referential data structures.
For starters, one must enable a non-default option (Purity) to handle them
at all.  The only reason I can imagine for this is that the default output
is slightly more readable; but this seems a small gain in exchange for a
higher chance of data loss.  Especially since code that doesn't set Purity
will likely work on (non-self-referential) test data, only to fail later.

Even with Purity, getting back the dumped data structure is gratuitously
tricky.  If the data is self-referential, one must eval the dump, then get
the data from $VAR1.  I can't imagine why the expression can't return $VAR1
directly.  Further, all of the documentation examples use the result of the
eval.  Again, this will work on test data, then fail later.  If one makes
the mistake of setting Terse (the documentation has an example using Terse
and Purity together), it is even worse, because $VAR1 will not always be
available.  There's also the matter of needing to turn off strict.

I guess the heart of the problem is that Data::Dumper is used both for
pretty-printing (though I don't know why; I find Dumpvalue more readable)
and for serialization; but the documentation short-changes the latter.  Some
examples:  "The contents of each variable is output in a single Perl
statement."--unless it is self-referential.  "Handles self-referential
structures correctly."--vague.  "The return value can be `eval'ed to get
back an identical copy of the original reference structure."--in general,
false.  "Any references that are the same as one of those passed in will be
named `$VAR'n"--not true under terse.

Finally, there are no examples of how to use Data::Dumper for reliable
serialization (or at least, as reliable as feasible, with caveats about
things like sub refs).  This is what I do:

    use Data::Dumper;

    $dumper = new Data::Dumper [ $data ];
    $dumped = $dumper->Purity(1)->Dump;
    ...
    {
        no strict 'vars';
        local $VAR1;
        eval $dumped;
        die "toast: $@" if $@;
        $data = $VAR1;
    }

But I'm not 100% sure of it.  I'm sure plenty of people have buggy code and
don't even know it.

What can be done?  Is there any chance of changing the default behavior to
be less error-prone?  If not, it would be nice if there were a section of
the documentation covering serialization, and if the misleading statements
in the introduction were clarified.  I will be happy to write it, if someone
can assure me that I have a grasp on the issues.  Of course, I will welcome
someone telling me I am way off base, as well.

Andrew

PS.  It is also inconvenient and confusing that one cannot reuse a $dumper
object on multiple data structures.

[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
    category=library
    severity=wishlist
---
Site configuration information for perl v5.6.0:

Configured by bod at Fri Mar  9 06:08:27 EST 2001.

Summary of my perl5 (revision 5.0 version 6 subversion 0) configuration:
  Platform:
    osname=linux, osvers=2.4.2, archname=i386-linux
    uname='linux duende 2.4.2 #1 fri mar 2 13:52:32 est 2001 i686 unknown '
    config_args='-Dccflags=-DDEBIAN -Darchname=i386-linux -Dprefix=/usr -Dprivlib=/usr/share/perl/5.6.0 -Darchlib=/usr/lib/perl/5.6.0 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.6.0 -Dsitearch=/usr/local/lib/perl/5.6.0 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/pager -Uafs -Ud_csh -Uusesfio -Duseshrplib -Dlibperl=libperl.so.5.6.0 -Dd_dosuid -des'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
    useperlio=undef d_sfio=undef uselargefiles=define 
    use64bitint=undef use64bitall=undef uselongdouble=undef usesocks=undef
  Compiler:
    cc='cc', optimize='-O2', gccversion=2.95.3 20010219 (prerelease)
    cppflags='-DDEBIAN -fno-strict-aliasing -I/usr/local/include'
    ccflags ='-DDEBIAN -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
    stdchar='char', d_stdstdio=define, usevfork=false
    intsize=4, longsize=4, ptrsize=4, doublesize=8
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=4, usemymalloc=n, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lnsl -ldl -lm -lc -lcrypt
    libc=/lib/libc-2.2.2.so, so=so, useshrplib=true, libperl=libperl.so.5.6.0
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic'
    cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:
    

---
@INC for perl v5.6.0:
    /home/pimlott/local/lib/perl5/i386-linux
    /home/pimlott/local/lib/perl5
    /usr/local/lib/perl/5.6.0
    /usr/local/share/perl/5.6.0
    /usr/lib/perl5
    /usr/share/perl5
    /usr/lib/perl/5.6.0
    /usr/share/perl/5.6.0
    /usr/local/lib/site_perl
    /usr/lib/perl5/5.6/i386-linux
    /usr/lib/perl5/5.6
    /usr/lib/perl5/5.005/i386-linux
    .

---
Environment for perl v5.6.0:
    HOME=/home/pimlott
    LANG=C
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/pimlott/bin:/usr/local/atria/bin:/home/pimlott/local/jdk1.3/bin:/home/pimlott/local/j2sdkee1.2.1/bin:/usr/sbin:/sbin:/home/pimlott/bin:/usr/local/atria/bin:/home/pimlott/local/jdk1.3/bin:/home/pimlott/local/j2sdkee1.2.1/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games
    PERL5LIB=/home/pimlott/local/lib/perl5
    PERL_BADLANG (unset)
    SHELL=/bin/zsh


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About