attached is 8k of module code (small enough to just send ?) with the candidate name;
Data::Dumper::Functor
This is a structural name, but other candidates are too ambiguous, and somewhat presumptuous;
DD::Easy, DD::Auto, DD::Lazy, DD::Brief
BTW - it has a package main section at bottom, you can just run it to see a simple sanity-test.
perl Functor.pm
Comments about the code itself are also welcome, off-list if you think that doesnt belong here.
tia jimc
#!perl
package Data::Dumper::Functor; use Data::Dumper; our VERSION = 0.01; =head1 NAME Data::Dumper::Functor - wraps DD for easy use of printing styles =head1 SYNOPSIS use Data::Dumper::Functor; { # build one my $ddf = Data::Dumper::Functor->new(indent=>1,terse=>1); # use ddf obj repeatedly print "default: ", $ddf->($_) for @userdata; # auto-labelling print "labelled: ", $ddf->(foo => $_) for @userdata; # alter existing functor, and reuse $ddf->Indent(0); print "default: ", $ddf->($_) for @userdata; # alter many params at once $ddf->Set(indent=>1,terse=>0,sortkeys=>1); print "default: ", $ddf->($_) for @userdata; } =head1 DESCRIPTION This package wraps Data::Dumper, and adapts its API for easier control of output format. =head1 Data::Dumper OO API usage problems this addresses In following docs, I often use DD as shorthand for Data::Dumper, and OO for its Object Oriented API. =head2 calls to OO-DD are Too Verbose For everything but exported Dumper(), invoking is needlessly baroque. This class provides a functor, so that printing data is as easy/brief as possible; you dont even need a method name! =head2 Too Hard to Label data print Data::Dumper->Dump([$a,$b,$c], [qw(a b c)]); This non-OO usage is just too punctuation intensive, too dependent on having exactly 2 arrayref args, and the label position is counterintuitive; ie after the data (ie: B<< tag => value >>). =head2 Format Control is Cumbersome { local $Data::Dumper::Indent = 1; local $Data::Dumper::Sortkeys = 1; print Dumper (@foo); } Without using OO form, your only choice wrt print-style is either localizing package variables each time you use Data::Dumper, or changing them globally. =head2 Early Binding of Data # OO usage foreach $datum (@data) { $d = Data::Dumper->new($datum); $d->Purity(1)->Terse(1)->Deepcopy(1); print $d->Dump; } In DD OO, you must provide the data to be dumped when the object is created. Only afterwards can you control that objects print format. This means lots of extra typing and function calls, thus discouraging use of OO style. I often live with indent=2, which I personally find harder to read than indent=1. =head1 FEATURES Ok, so the functor thing may be over-cool, after all $d->Dump isnt so bad. It was an experiment (in blessed coderefs) that went well enough to polish and publish. =head2 Auto-Labelling Arguments are checked to see if they can be interpreted as labels, ie values at odd indexes must be scalars. If this test passes, the data is rendered using DD labelling feature, see L<"Too Hard to Label Data"> above. This maybe a bit aggressive for your tastes, but I dont often use DD with simple scalars, and my habit with Dumper() is to always pass a single data-arg anyway. YMMV. =head2 Speed Untested yet, but Dumper() builds a new DD object for each print, which presents opportunities for real runtime improvements. The 'cost' is some hackery at Data::Dumper internals. =head1 Possible Applications A client-class dumper. With a singleton in a pkg-var or file-my-var, you can set the B<sortkeys> attr to dump only the object keys you care to see for debugging purposes. A small number of such specialists should serve all your needs. =head1 IMPLEMENTATION The class builds a blessed CODEref object, for which perl also allows method-lookups. This hybrid nature is key to the viability of the design. new() builds a Data::Dumper object, then builds and returns a closure on that DD object. The closure provides the interface to DD::Dump, and also provides access to the underlying DD object for the other methods; Set() and AUTOLOAD(). AUTOLOAD() provides an interface to all of DDs format-control and maintenance methods. Set() is a 'convenience' method that allows setting of multiple DD properties simultaneously. AUTOLOAD actually calls Set(), as the latter checks that the properties being set have a corresponding setter method. Set() doesnt provide accessor facilities, as most of the functions return the DD object in support of method chaining, and thus cannot return the attribute values. =head1 CAVEATS Brand new code. developed on 5.8.2, and may be dependent on advanced features. No version dependency in yet, Im hoping CPANTS will tell me ;-) too much dependency on DD attrs, partly/mostly/completely solvable with existing DD methods format control not per-use (object only) it may be possible to use 'defined wantarray' to implement. no global format control (will add import tags) auto-labelling may be overzealous. flexibility wrt capitalization of attr/methods can issue warnings with different capitalization from usage not *entirely* data-agnostic, pass '__SA__' to functor iff you want the underlying DD object Comments welcome. =head1 ACKNOWLEDGMENTS Gurusamy Sarathy for writing DD, I love it and use it *ALL* the time, its often my microscope of choice. I cant leave the above critique as the only commentary. =head1 AUTHOR Jim Cromie <[EMAIL PROTECTED]> Copyright (c) 2003 Jim Cromie. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. I dont suppose Ill ever recover the development time via reduced keystrokes, but CPAN has saved me so much already; heres a little give-back. Anyway, perl is fun, like an always-new toy. =cut ################## package Data::Dumper::Functor; use Data::Dumper; use Carp 'carp'; sub AUTOLOAD { my ($ddf, $arg) = @_; (my $meth = $AUTOLOAD) =~ s/.*:://; return if $meth eq 'DESTROY'; $ddf->Set($meth,$arg); } # 1 forces method test via symbol table my $viasymtbl = 0; # 1 doesnt work ! sub Set { # sets internal state of private data dumper object my ($ddf, %cfg) = @_; my $ddo = $ddf->('__SA__') if ref $ddf eq __PACKAGE__; #print "setting ddo: ", Dumper $ddo, \%cfg if %cfg; for my $item (keys %cfg) { #print "$item => $cfg{$item}\n"; if ($viasymtbl) { my $meth = ucfirst $item; unless (\&{"Data::Dumper::$meth"}) { carp "illegal $item on DDobj\n" .\&{"Data::Dumper::$meth"}; next; } $ddo->$meth($cfg{$item}); } else { # direct ddo update my $meth = ucfirst $item; my $attr = lc $item; unless (exists $ddo->{$attr}) { carp "illegal method <$attr>"; next; } # eval { $ddo->$meth($cfg{$item}) }; carp "illegal method <$attr>" if $@; } } } sub new { my ($cls, %cfg) = @_; my $ddo = Data::Dumper->new([]); # bogus data Set($ddo, %cfg); my $code = sub { # closure on $ddo my @args = @_; $ddo->Reset unless $ddo->{ddf_noreset}; if (@args == 1) { # special access for AUTOLOAD return $ddo if $args[0] eq '__SA__'; # else Regular usage $ddo->{todump} = [EMAIL PROTECTED]; return $ddo->Dump(); } # else if (not @args % 2) { # possible labelled usage - check! my %rev = reverse @args; if (grep {ref $_} values %rev) { # odd elements are refs. print as array $ddo->{todump} = [EMAIL PROTECTED]; return $ddo->Dump(); } my (@labels,@vals); while (@args) { push @labels, shift @args; push @vals, shift @args; } $ddo->{todump} = [EMAIL PROTECTED]; $ddo->{names} = [EMAIL PROTECTED]; return $ddo->Dump(); } else { $ddo->{todump} = [EMAIL PROTECTED]; return $ddo->Dump(); } }; #print $code; return bless $code, $cls; } package main; if ($0 =~ /Functor\.pm$/) { $foo = [qw/ hello there /]; $bar = {qw/ alpha 1 beta 2 zed 26 /}; $baseline = Data::Dumper->new([$foo], ['foo']); print $baseline->Dump(); my $ddf = Data::Dumper::Functor->new; print "new thingy: ", Dumper $ddf; print "used on \$foo: ", $ddf->($foo); print "used on \$bar: ", $ddf->($bar); print "w label \$foo: ", $ddf->(foo=>$foo); print "w label \$bar: ", $ddf->(bar=>$bar); $ddf->Indent(1); print "used on $foo: ", $ddf->($foo); $ddf->Set(indent=>1,sortkeys=>1); print "used on bar: ", $ddf->($bar); $ddf->poop(1); #print "used on $foo: ", $ddf->($foo); } 1; __END__