After reading a recent Perl question on here about checking if a value exists in an array left me thinking about how to do this. I see most people recommending the grep option in the form
if (!grep { $input_day eq $_ } @days ) {
say "Grep Invalid Day";
}
However when I read this question my first through jumped to the smart match operator
unless ( $input_day ~~ @days ) {
say "Smart Invalid Day";
}
So it got me wondering if there is any benefit of using grep over smart-match or vice versa. I know smart-match is only available in later versions of Perl so is not something that can be recommend for people with a Perl version before 5.10.1.
I have never really bench-marked Perl code before so the below code was written from an example online. I have tried running the smart match example 2 million times and the grep example 2 million times and recording the timing.
use strict;
use warnings;
use v5.16.2;
use Benchmark;
my $input_day = shift;
my @days = qw /mon tue wed thu fri sat sun/;
my $smart_test_start = new Benchmark();
for(my $x=0; $x<10000000; $x++){
unless ( $input_day ~~ @days ) {
#here we would execute some code
}
}
my $smart_test_end = new Benchmark();
my $grep_test_start = new Benchmark();
for(my $y=0; $y<10000000; $y++){
if (!grep { $input_day eq $_ } @days ) {
#here we would execute some code
}
}
my $grep_test_end = new Benchmark();
my $smart_diff = timediff($smart_test_end, $smart_test_start);
my $grep_diff = timediff($grep_test_end, $grep_test_start);
say "SMART: ", timestr($smart_diff,'all');
say "GREP: ", timestr($grep_diff,'all');
I used a few different inputs.
Input "mon"
SMART: 3 wallclock secs ( 2.75 usr 0.00 sys + 0.00 cusr 0.00 csys = 2.75 CPU)
GREP: 12 wallclock secs (12.02 usr 0.01 sys + 0.00 cusr 0.00 csys = 12.03 CPU)
Input "thu"
SMART: 6 wallclock secs ( 5.67 usr 0.00 sys + 0.00 cusr 0.00 csys = 5.67 CPU)
GREP: 11 wallclock secs (11.46 usr 0.01 sys + 0.00 cusr 0.00 csys = 11.47 CPU)
Input "sun"
SMART: 8 wallclock secs ( 8.87 usr 0.01 sys + 0.00 cusr 0.00 csys = 8.88 CPU)
GREP: 12 wallclock secs (11.62 usr 0.00 sys + 0.00 cusr 0.00 csys = 11.62 CPU)
Input "non"
SMART: 9 wallclock secs ( 8.46 usr 0.00 sys + 0.00 cusr 0.00 csys = 8.46 CPU)
GREP: 11 wallclock secs (11.58 usr 0.13 sys + 0.00 cusr 0.00 csys = 11.71 CPU)
In all the cases the smart match operator seems to perform better than the grep. Looking at the results, i assume in the early use cases this is because the smart-match will stop as soon as it finds a match where as the grep will continue checking the rest of the array after matching the first occurrence.
I then see other people recommending to use certain modules to find the first instance etc.
Is there some reason people don't recommend the smart-match operator? Is there some limitation or unreliability in smart-match?
any
fromList::MoreUtils
– Borodin