in reply to Re^9: Specializing Functions with Currying
in thread Specializing Functions with Currying

I sometimes fall foul of that too. My most recent example was:

my $first = first{ length > 3 } @array; print $first;

Versus:

my $first; for ( @array ) { next unless length > 3; $first = $_; last; } print $first;

where, despite the compiled-loop nature of List::Util::first, the latter was considerably more efficient than the former if the required value was close to the front of the array.

Nearly twice as efficient with an array of 100,000 items and the thing I was looking for about a 10th of the way in.

Funnily enough, even if the item I was looking for was the last item in the array, the iterative approach was still quickest. I guess the penalty of entering and exiting the block scope is the cause?


Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon

Replies are listed 'Best First'.
Re^11: Specializing Functions with Currying
by Aristotle (Chancellor) on Aug 09, 2004 at 14:12 UTC

    first is pure-Perl and does not have short-circuiting behaviour.

    Use the source, Luke. It's what it's there for. :-)

    Makeshifts last the longest.

      first is pure-Perl and does not have short-circuiting behaviour.

      And if you look at the the source just before the pure perl reduce definition we find:

      eval <<'ESQ' unless defined &reduce; # This code is only compiled if the XS did not load

      :-)

      So the reduce() in question may, or may not, be pure perl.

        Oops.

        Interesting, also, that the XS version does short-circuit. I looked at the source and thought I could see that, but I don't know XS so to be sure, I tested. And lo:

        $ perl -MList::Util=first -le'@_=(0)x100; first { ++$a; $_ == 0 } @_; +print $a' 1

        Hmm.

        Makeshifts last the longest.

      I did... :)

      P:\lib\auto\List\Util>strings Util.dll | grep Usage Usage: List::Util::reduce(block, ...) Usage: List::Util::first(block, ...) <<<<<<<<<<<<<<<<<< Usage: Scalar::Util::dualvar(num, str) Usage: Scalar::Util::blessed(sv) Usage: Scalar::Util::reftype(sv) Usage: Scalar::Util::refaddr(sv) Usage: Scalar::Util::weaken(sv) Usage: Scalar::Util::isweak(sv) Usage: Scalar::Util::readonly(sv) Usage: Scalar::Util::tainted(sv) Usage: Scalar::Util::isvstring(sv) Usage: Scalar::Util::looks_like_number(sv) Usage: Scalar::Util::set_prototype(subref, proto)

      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon

        Weird.

        use Benchmark qw(cmpthese); use List::Util qw(first); @_= ( (0)x1000, 1, (0)x8999 ); cmpthese -1, { func => sub { first { $_ == 1 } @_ }, imper => sub { for ( @_ ) { next unless $_ == 1; return $_ } }, } __END__ Rate imper func imper 518950/s -- -20% func 649177/s 25% --

        Makeshifts last the longest.