Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Data-Printer CPAN distribution.

Report information
The Basics
Id: 68589
Status: resolved
Priority: 0/
Queue: Data-Printer

People
Owner: Nobody in particular
Requestors: DAMS [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: 0.17



Subject: protorype on p() makes the module not very useful
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.
On Wed Jun 01 04:45:15 2011, DAMS wrote: Show quoted text
> 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 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? Please don't take me for ironic here, I really want to know. The reason why it *does* use prototypes is twofold: 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 ...). 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. 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. One thing I'd like to do is allow multiple variables in the same call, like: p @foo, %bar, $baz; and I don't think prototypes let me do that (patches welcome!). 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. 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 } ); 2) Create a tiny sub in your application wrapping p(): sub pp { p @_ } Then you'll be able to write: pp { foo => 42 }; I'll make sure to add those to the documentation.
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
On Thu Jun 02 15:02:52 2011, DAMS wrote: Show quoted text
> 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 :) >
As of version 0.17, you can say: use Data::Printer use_prototypes => 0; (or add it to your .dataprinter file and never worry about it again) after that, p() will have no prototypes and let you do things like: p \"I am here!"; p { foo => 42 }; p [ $foo, 'bar', 42 ]; and even: p my $foo = Foo->new; But remember that you will have to make sure the first argument is a REFERENCE. p @var; # this will NOT work without prototypes p \@var; # do this instead :) Just as a sidenote, since you mentioned it, you CAN do: p $foo->bar; even with prototypes :) Does that suit your needs? If so, please let me know so I can close the ticket. Thanks again for the bug report and for the nice discussion!
On Tue Jun 07 01:48:43 2011, GARU wrote: Show quoted text
> On Thu Jun 02 15:02:52 2011, DAMS wrote:
> > 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 :) > >
> > As of version 0.17, you can say: > > use Data::Printer use_prototypes => 0; > > (or add it to your .dataprinter file and never worry about it again) > > after that, p() will have no prototypes and let you do things like: > > p \"I am here!"; > p { foo => 42 }; > p [ $foo, 'bar', 42 ]; > > and even: > > p my $foo = Foo->new; > > But remember that you will have to make sure the first argument is a > REFERENCE. > > p @var; # this will NOT work without prototypes > p \@var; # do this instead :) > > Just as a sidenote, since you mentioned it, you CAN do: > > p $foo->bar; > > even with prototypes :) > > Does that suit your needs? If so, please let me know so I can close the > ticket.
Hi, That does the trick :) Thanks for the quick fix !