Skip Menu |

This queue is for tickets about the List-MoreUtils CPAN distribution.

Report information
The Basics
Id: 102217
Status: rejected
Priority: 0/
Queue: List-MoreUtils

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

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



Subject: all, any, none, notall: suggested prototype change to better match builtin 'map'
'none' and friends have a prototype to behave like perl's builtin 'map'. This means that you can say % perl -wE 'use List::MoreUtils qw(none); say none { say "hi" } 2, 3' and have the first argument recognized as an anonymous sub, without needing the 'sub' keyword. (Obviously printing 'hi' is not a useful filter, I just have it for an example.) This is similar to % perl -wE 'say map { say "hi" } 2, 3' There is no comma between the end of the filter block and the next argument. Suppose the programmer makes a mistake and puts a comma in. With map, the error is obvious: % perl -wE 'say map { say "hi" }, 2, 3' syntax error at -e line 1, near "}," But with none, the effect is to change the precedence, so that only the first element in the list becomes an argument to none, with the rest going to say: % perl -wE 'use List::MoreUtils qw(none); say none { say "hi" }, 2, 3' 123 This is unfortunate - it would be much better for the misplaced comma to give an error as with map. But I believe there is a solution. I think the current prototype is none(&@), is that right? If so, you can see the same problem with a pure-Perl implementation: % perl -wE 'sub none(&@) { my $f = shift; local $_; foreach (@_) { return 0 if &$f } return 1 } say none { say "hi" }, 2, 3' 123 Changing the prototype to none(&$@) gives a compile-time error as desired: % perl -wE 'sub none(&$@) { my $f = shift; local $_; foreach (@_) { return 0 if &$f } return 1 } say none { $_ eq "a" }, 2, 3' Not enough arguments for main::none at -e line 1, near "}," Doesn't that mean that none can no longer be called on an empty list? Luckily it doesn't. An explicit empty list is still fine: % perl -wE 'sub none(&$@) { my $f = shift; local $_; foreach (@_) { return 0 if &$f } return 1 } say none { $_ eq "a" } ()' 1 The only existing code affected would be code which has a hardcoded call to none with a code block and nothing afterwards - or, perhaps, code which has the comma mistake above. In both cases, explicit parens can be used if for some reason you really want the rather pointless call of none on no elements. Could you change the prototype of all, any, none, and notall from (&@) to (&$@) to get the improved diagnostic and consistent behaviour with map?
RT-Send-CC: MSTROUT [...] cpan.org, dagolden [...] cpan.org
Hi Ed, thanks for contributing to List::MoreUtils. No, I will not change the API of existing functions in List::MoreUtils - and for Perl5 you're suggestion isn't suitable. Likely you could implement the junctions as op's as map is - that could help. Patches welcome. I will not (mind RT#98583) implement syntactic sugar for a subset of use-cases where perl itself provides enough features to solve it out of the box. I don't know the consequences of your suggestion, but this makes me scary: #!perl use v5.10; sub none (&$@) { my $f = shift; foreach ( @_ ) { return 0 if $f->(); } return 1; } my @l = qw(foo bar); my @e; say none { say "hi: $_" } 2, 3; say none { say "blub: $_" } @l; say none { say "bla: $_" } @e; -- $ perl test.pl hi: 2 0 blub: 2 0 bla: 0 0 Yes: The list is converted to a scalar containing the amount of list elements. This is unintensional!
Thanks for looking at this. You are right that the prototype change breaks other things - I hadn't spotted that. I guess we have to live with the unfortunate parsing when there's an extra comma :-(. Thanks for reminding me about the other bug - I need to make some time to work on that.