http://www.perlmonks.org?node_id=1067501


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

so this should be a fast and core fallback if no better module available.

DB<125> @a=(0)x10 => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0) DB<126> sub any (&@) { my $cr=shift; defined first { &$cr } @_ } DB<127> any {$_==0} @a => 1

well could be faster if I could avoid '$cr' but my golfing foo is weak today. =)

update

got it :)

DB<138> sub any (&@) { defined &first (shift, @_) } DB<139> any {$_==0} @a => 1

update

better :)

DB<144> sub any (&\@) { defined &first } DB<145> any {$_==0} @a => 1

UPDATE

DARN! still buggy with false positives!

didn't sleep enough...

update

this seems to work...

DB<230> sub any (&@) { my $x=&List::Util::first; defined $x } DB<231> any { $_ eq 0 } @a => "" DB<232> any { $_ eq 5 } @a => 1 DB<233> @a => (1, 2, 3, 4, 5)

Cheers Rolf

( addicted to the Perl Programming Language)

Replies are listed 'Best First'.
Re^5: Smartmatch alternatives
by tobyink (Canon) on Dec 17, 2013 at 19:01 UTC

    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
      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)

      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