Beefy Boxes and Bandwidth Generously Provided by pair Networks Frank
Syntactic Confectionery Delight
 
PerlMonks  

Re^5: Smartmatch alternatives

by tobyink (Abbot)
on Dec 17, 2013 at 19:01 UTC ( #1067509=note: print w/ replies, xml ) Need Help??


in reply to Re^4: Smartmatch alternatives
in thread Smartmatch alternatives

Works fine until you want to see if an array contains any false values...

use Data::Dumper; use List::Util (); sub any (&@) { my $x = &List::Util::first; defined $x } my @x = (1..3, undef, 5..10); # undef is false print Dumper(any { !$_ } @a);
use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name


Comment on Re^5: Smartmatch alternatives
Download Code
Re^6: Smartmatch alternatives
by LanX (Abbot) on Dec 17, 2013 at 22:08 UTC
    Thanks, but this can't be fixed.

    The problem is that the design of List::Util first is broken, no result should be an empty list and not undef! At least in list context ! :(

    DB<28> \@x => [1, 2, 3, undef, 5, 6, 7, 8, 9, 10] DB<29> @a=List::Util::first { !$_ } @x; \@a => [undef] DB<30> @a=List::Util::first { $_ eq "never" } @x; \@a => [undef]

    I wished people would learn the lesson that () is always better then undef for failure in list operations like iterators or filters.

    update

    grep does it right!

    DB<38> @a=grep { !$_ } @x; \@a => [undef] DB<39> @a=grep { $_ eq "never" } @x; \@a => []

    Cheers Rolf

    ( addicted to the Perl Programming Language)

Re^6: Smartmatch alternatives
by LanX (Abbot) on Dec 17, 2013 at 22:57 UTC
    hmm maybe simpler than we thought!

    DB<25> sub first (&@) { my $code=shift; grep {return $_ if &$code} @ +_ } DB<26> first { $_ >5 } 1..10 => 6 DB<27> first { $_ >10 } 1..10 DB<28> sub any (&@) { my $code=shift; grep {return 1 if &$code} @_ ; + ()} DB<29> any { $_ >10 } 1..10 => "" DB<30> any { $_ >5 } 1..10 => 1

    Can you spot problems?

    update

    variation of first for finding position

    DB<40> sub position (&@) { my $code=shift; my $idx=-1; grep {++$idx; + return $idx if &$code} @_ ; ()} DB<41> position { !$_ } 1..10,undef,11..20 => 10

    update

    changed "" to () for false.

    update

    even easier

    DB<53> sub first (&@) { my $code=shift; &$code and return $_ for @_ +; ()} DB<54> sub any (&@) { my $code=shift; &$code and return 1 for @_ ; ( +)}

    Cheers Rolf

    ( addicted to the Perl Programming Language)

      These look fine to me. IIRC, older versions of List::Util included a non-XS implementation of first; current versions of List::MoreUtils include a non-XS version of any. So pure Perl versions can probably be pilfered from them too.

      use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
        I'm starting to doubt if XS is really worth it.

        Beside the hard to fix bugs, these modules are not that much faster.

        In my benchmarks pure Perl5.10 approaches of any were in the range of 80%-50% of the speed of List::MoreUtils !

        Interesting is

        • map and grep were faster than for!
        • directly hard coding the condition instead of calling a coderef wasn't faster!
        • List::Util was slower than pure Perl

        Rate PP_for LU_first PP_grep PP_map PP_mapdirec +t LMU_any PP_for 323355/s -- -4% -9% -16% -18 +% -47% LU_first 335913/s 4% -- -6% -13% -15 +% -45% PP_grep 356464/s 10% 6% -- -8% -10 +% -42% PP_map 387000/s 20% 15% 9% -- -2 +% -37% PP_mapdirect 395959/s 22% 18% 11% 2% - +- -35% LMU_any 612649/s 89% 82% 72% 58% 55 +% --

        Have to repeat the benchmark with more test cases...

        Cheers Rolf

        ( addicted to the Perl Programming Language)

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1067509]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (9)
As of 2014-04-16 23:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (436 votes), past polls