Le Jeu 02 Juin 2011 11:08:40, GARU a écrit :
Show quoted text> On Wed Jun 01 04:45:15 2011, DAMS wrote:
> > perl -e 'use Data::Printer; p( { foo => 42 });'
> > Type of arg 1 to Data::Printer::p must be one of [@$%&] (not anonymous
> > hash ({})) at -e line 1, near "})"
> >
> > That's because the p() method has a strict prototype. Maybe it's useful
> > to have these prototypes, maybe it's mandatory, I don't know :)
> >
> > But having this prototype makes the module almost unusable in real life.
> >
> > I tried removing the prototype of the p() function, and it works fine
> > for me, I can do p( { foo => 42 }); Maybe it breaks other stuff but I
> > don't think so.
>
> Hi there! Thanks for trying Data::Printer and taking the time to file
> this report.
You're welcome, thanks for providing this nice piece of software :)
Show quoted text>
> You say that "having this prototype makes the module almost unusable in
> real life" and it's a pretty bold statement. Can you please provide more
> information on this?
Indeed, it's a bold statement, I shouldn't have phrased it like that, sorry. I didn't mean to be
rude or so.
What I basically mean is that the prototypes makes it impossible to use p() as a full
replacement for a printer.
Usually, you want to print debug messages, some information, dump existing variables, and
dump structure you build on the fly. Without the protoypes, you can use p() for everything :
p "debug : in warp zone";
p "message is [$message]";
p $structure
p map { $_->stringify } %$structure
With the prototypes, you have to take time and think about what you can use to output
something. Either print when it's a string, Data::Dumper when it's an anonymous structure, or
p when it's a named structure. That's annoying, and so it tends to be unusable for everyday
work. Hence my bold statement :)
Show quoted text> First, allowing developers not to care whether they should print the
> variable or a reference to it. I've seen a lot of people, specially
> newcomers, make this mistake in Data::Dumper, doing Dumper( @var ) when
> they should do Dumper( \@var ). Data::Dump tries to do fix this but
> since it doesn't offer prototypes it mistakes everything that's not a
> reference to a simple list, which might produce misleading results. The
> way to fix that is via prototypes, so I know whether the variable is a
> scalar or array or hash (or glob, or ...).
Well, I would say that I prefer the way Data::Dump does it (never used it but seems more
logical) : if there is more than one argument, wrap them all in a list or list reference. It can
still be displayed nicely. I think it matters even less for Data::Printer, as what we need is to
see the content, not be picky about if it's a list or a list reference.
But that is my personal opinion, and I don't want to push anything here.
Show quoted text>
> Second, it allows the (experimental) feature of inline properties, like:
>
> p %some_var, multiline => 0;
>
> If we remove the prototypes, we'd have to either force a reference as
> first argument, remove this feature, put it somewhere else, or do some
> black magic to detect whether the last argument is part of a structure
> to be printed or part of the customization options.
>
> So yeah, not having prototypes breaks other stuff :)
>
> In the real world you want to inspect a variable, not try to print { foo
> => "bar" }, and this is why I figured prototypes wouldn't be such a big
> deal.
Well, it turns out that usually the structure you want to inspect is not directly available in a
nice local variable. It's either an object attribute $self->{foo} or with Moose-like stuff : $self-
Show quoted text>foo(), or it's a sub structure of a big structure ($customer->{previous_basket}).
I have 10 years of Perl professional experience, and I'd tend to say that on the contrary, in the
real world you don't want to inspect a variable, you want to print { foo => $stuff } :) But I'm a
dinosaur :)
Show quoted text>
> That said, I don't like using them just as the next person and would
> gladly remove them if we can provide its benefits in some alternative
> way.
Well I don't know, maybe you can provide 2 methods : one for general data printing (without
prototypes), and one for variable printing. For instance :
var_printer($foo) # with prototypes
data_printer({ some => $stuff}) # without prototypes
Show quoted text> One thing I'd like to do is allow multiple variables in the same
> call, like:
>
> p @foo, %bar, $baz;
Hmm, that would be a valid argument. However, I never use a data printer/dumper to dump
more than one value. I never saw anyone having that need either, but again, I'm subjective.
Usually I use data dumping for debugging, and dumping one structure at a time usually
makes it.
Show quoted text>
> and I don't think prototypes let me do that (patches welcome!).
Indeed I don't know :/ I'm not too good with prototypes :)
Show quoted text>
> The only "real world" scenario where I see printing anonymous structures
> really useful it letting one do this:
>
> p { foo => \@foo, bar => \%bar, baz => $baz };
>
> but when I compare it with the current alternative:
>
> p @foo; p %bar; p $baz;
>
> I find the latter shorter, simpler and more straight to the point -
> specially in the next version of Data::Printer where you'll even be able
> to see the name of the variable.
Ah that would be interesting indeed.
However, plese refer to my earlier examples.
Show quoted text>
> Finally, there are workarounds for prototypes that I should mention in
> the docs to assist cases where anonymous structures are wanted:
>
> 1) Simply add a "&" to the call, effectively circumventing the prototypes:
>
> &p( { foo => 42 } );
Ah clever, I didn't think of that
Show quoted text>
> 2) Create a tiny sub in your application wrapping p():
>
> sub pp { p @_ }
Yup, that's what I ended doing. One aadditional thing : exporting p() by default is not that
awesome, because :
- there is good chance it'll clash with the existing code, if it's a big software, so people will
have to alias it
- people may not like p(), but prefer something else. I preferred dp() and ended up with
data_printer. Sure it's longer to type than p(), but we all have autocompletion in our editors,
don't we ?
To summarize, this is what I propose, but you're free to do as you like of course :)
don't export p(), but instead, export :
data_printer : without prototypes, an all-included tool, you can use it for printing, dumping,
etc.
var_printer : with prototypes, to be used on variables, with nice display (and variable names)
Thanks again for the code and the reply :)
dams