John M. Dlugosz has asked for the wisdom of the Perl Monks concerning the following question:

I want to show the definition of a hash, suitable for pasting into code (e.g. this is a code generator/alterer). Dumper is a good idea, since it does all the hard work about quoting and indenting and everything, and is supposed to produce code that parses and runs (within known limits).

But, it can't handle code references. Any code ref is turned into DUMMY.

So, can I get Dumper or something like it to call-back specified hash keys so I can emit the proper string for it with my own logic, and still let it handle all the rest of them?

—John

Replies are listed 'Best First'.
Re: Data::Dumper is not quite what I want.
by pg (Canon) on Dec 27, 2002 at 05:48 UTC
    You can simply turn on the Deparse option of Data::Dumper:
    use Data::Dumper; sub a { print "abc"; } sub b { print "123" } $hash = {"a",\&a, "b", \&b}; $Data::Dumper::Deparse = 1; print Dumper($hash);
    It also works with anonymous:
    use Data::Dumper; sub b { print "123" } $hash = {"a",sub {print "abc"}, "b", \&b}; $Data::Dumper::Deparse = 1; print Dumper($hash);
    But there is caution stated in the doc, check it.
      That's not mentioned in my copy (came with ActiveState 5.6.1). I guess it was added in a newer version, and AS doesn't track the latest versions of modules with their updates.

      —John

Re: Data::Dumper is not quite what I want.
by jryan (Vicar) on Dec 27, 2002 at 05:24 UTC

    First, recursively walk through the hash, and use the new version of Storable to serialize all code-references. Now you can use Data::Dumper to dump the hash. Easy.

    use Storable qw(freeze thaw); sub rec_walk { my $hash = shift; foreach (keys %$hash) { if (ref $hash->{$_} eq 'CODE') { $hash->{$_} = freeze $hash->{$_} } elsif (ref $hash->{$_} eq 'HASH') { $hash->{$_} = rec_walk($hash->{$_}) } } $hash } my %hash = (...); print Dumper rec_walk(\%hash);
Re: Data::Dumper is not quite what I want.
by princepawn (Parson) on Dec 27, 2002 at 08:37 UTC
    I used to think serializing coderefs was what I wanted. It turned out that I could have simply put the code of the coderefs into a class, then serialize an object of that class, then simply call the object methods after reblessing/creating the object.

    Carter's compass: I know I'm on the right track when by deleting something, I'm adding functionality

Re: Data::Dumper is not quite what I want.
by theorbtwo (Prior) on Dec 27, 2002 at 05:24 UTC

    I see several solutions. You could use tie to change the stringification of your coderefs (I think). You could just emit code to chage the DUMMYies after the Data::Dumper generated code. You could do some sort of parsing of the Data::Dumper output. You could write the thing yourself. You could use another serialization provider that /does/ provide the ablity to hook into it. You could use the Toaster or Freezer methods of Dumper (though I'm not sure how well they'd work for you).

    Oh, bingo: See the examples section of the docs, and the Seen method.


    Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).

      The only example that uses Seen gives me "Only refs supported, ignoring non-ref item $*c" on the call to Seen.