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


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

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)

Replies are listed 'Best First'.
Re^7: Smartmatch alternatives
by tobyink (Canon) on Dec 18, 2013 at 00:11 UTC

    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)

        Really? In my benchmarks, the XS versions are significantly faster. The List::Util XS version is faster than List::MoreUtils too.

        use strict; use warnings; use Benchmark qw(cmpthese); use List::Util 1.35 (); BEGIN { *any_lu = *List::Util::any }; use List::MoreUtils (); BEGIN { *any_lmu = *List::MoreUtils::any }; sub any_pp (&@) { my $code = shift; &$code and return 1 for @_ ; () } { no warnings 'once'; @::LIST = (0..9); $::TARGET = 5; } cmpthese(-1, { any_lu => q[ any_lu { $_ eq $::TARGET } @::LIST ], any_lmu => q[ any_lmu { $_ eq $::TARGET } @::LIST ], any_pp => q[ any_pp { $_ eq $::TARGET } @::LIST ], }); __END__ Rate any_pp any_lmu any_lu any_pp 65761/s -- -79% -80% any_lmu 309688/s 371% -- -5% any_lu 324588/s 394% 5% --

        For longer lists, the difference becomes more pronounced:

        { no warnings 'once'; @::LIST = (0..99); $::TARGET = 50; } ... __END__ Rate any_pp any_lmu any_lu any_pp 10195/s -- -84% -85% any_lmu 63999/s 528% -- -4% any_lu 66370/s 551% 4% --
        use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name