Actualy i think you are wrong. ;) Unless my bechmark is way off (which if could be). Any that takes a sub beats the original any and grep hands down everytime. By a rather large margin in fact, and the margin grows substantialy with the size of the data.
use strict;
use warnings;
use Benchmark qw/cmpthese/;
sub any_1 { $_ && return 1 for @_; 0 }
sub any_2 {
my $code = shift;
$code->($_) && return 1 for @_;
0;
}
my @data;
push @data, int rand 50 for 1..100;
my @large_data;
push @large_data, int rand 50 for 1..10_000;
cmpthese(-5, {
any_1_small => sub { any_1( map { $_ > 20 } @data); },
any_2_small => sub { any_2( sub { $_ > 20 }, @data); },
grep_small => sub { scalar grep{ $_ > 20 } @data; },
});
cmpthese(-5, {
any_1_large => sub { any_1( map { $_ > 20 } @large_data); },
any_2_large => sub { any_2( sub { $_ > 20 }, @large_data); },
grep_large => sub { scalar grep{ $_ > 20 } @large_data; },
});
__END__
Rate any_1_small grep_small any_2_small
any_1_small 8962/s -- -84% -96%
grep_small 56517/s 531% -- -73%
any_2_small 209808/s 2241% 271% --
Rate any_1_large grep_large any_2_large
any_1_large 57.3/s -- -90% -99%
grep_large 550/s 860% -- -89%
any_2_large 5052/s 8723% 819% --
Perhaps I missed your point but it definitly seems that calling a function is better in this case. That is probably because it short circuits quite soon and avoids alot of unneeded workd./me goes to run some tests for when any would fail.
UPDATE:
I benchmarked some more for less matches and no matches.
use strict;
use warnings;
use Benchmark qw/cmpthese/;
sub any_1 { $_ && return 1 for @_; 0 }
sub any_2 {
my $code = shift;
$code->($_) && return 1 for @_;
0;
}
my @data;
push @data, int rand 50 for 1..1000;
cmpthese(-5, {
any_1_20 => sub { any_1( map { $_ > 20 } @data); },
any_2_20 => sub { any_2( sub { $_ > 20 }, @data); },
grep_20 => sub { scalar grep{ $_ > 20 } @data; },
});
cmpthese(-5, {
any_1_45 => sub { any_1( map { $_ > 45 } @data); },
any_2_45 => sub { any_2( sub { $_ > 45 }, @data); },
grep_45 => sub { scalar grep{ $_ > 45 } @data; },
});
cmpthese(-5, {
any_1_60 => sub { any_1( map { $_ > 60 } @data); },
any_2_60 => sub { any_2( sub { $_ > 60 }, @data); },
grep_60 => sub { scalar grep{ $_ > 60 } @data; },
});
__END__
Rate any_1_20 grep_20 any_2_20
any_1_20 687/s -- -88% -99%
grep_20 5583/s 713% -- -92%
any_2_20 72133/s 10400% 1192% --
Rate any_1_45 grep_45 any_2_45
any_1_45 682/s -- -89% -97%
grep_45 6013/s 781% -- -75%
any_2_45 24282/s 3459% 304% --
Rate any_2_60 any_1_60 grep_60
any_2_60 625/s -- -3% -90%
any_1_60 645/s 3% -- -89%
grep_60 6017/s 863% 833% --
Grep takes a nice lead when there will be no matche, but any_2 still holds even with any_1, so at worst its only as bad as any_1 and no slower.
|