Reputation: 25996
I just upgraded to Perl 5.26.1, now I get
Smartmatch is experimental at check_tr.pl line 67.
where the code in question is
my @patterns = (qr/summary:\s+(.+?) in\s+(.+?) - average of\s+(.+?)$/,
qr/summary:\s+(.+?) in\s+(.+) (.+? .+?)$/);
my $r = "";
opendir(DIR, $dir) or die $!;
while(my $file = readdir(DIR)) {
next if ($file =~ m/^\./);
open(F, '<', "$dir/$file") or die $!;
if (<F> ~~ @patterns) {
$r .= <F>;
...
Question
Ideally with as few changes to the code as possible. What should I do instead of smart matching?
Upvotes: 8
Views: 7832
Reputation: 180
For situations where you have several shapes of data to compare with, and you don't want a long list of if / elsif in your code to go over all possible situations, then the match::simple module by TOBYINK is a pretty good replacement for the old smartmatch.
Upvotes: 0
Reputation: 4075
Have to agree with the other answers that Perl's smartmatch is better avoided.
There is a list of alternatives (with examples) on Perl-Monks site:
PerlMonks - Smartmatch alternatives
Upvotes: 2
Reputation: 4104
The reason Smartmatch is experimental is that it is so hard to figure out what it will do without referencing the Docs. Even so, how do we interperet the above code?
Is this a case of:
ARRAY1 ARRAY2 recurse on paired elements of ARRAY1 and ARRAY2[2]
like: (ARRAY1[0] ~~ ARRAY2[0])
&& (ARRAY1[1] ~~ ARRAY2[1]) && ...
Where we presume <F>
is interpreted in list context and emptied in a single call?
Or is this a case of:
Any ARRAY smartmatch each ARRAY element[3]
like: grep { Any ~~ $_ } ARRAY
I'm going to guess the 2nd. In which case the snippet above from the docs gives you an excellent (and clearer) coding alternative. Presuming @patterns
contains regexes, you can also replace the ~~
with =~
.
If you don't like the grep
alternative from the docs, I'd recommend looking into either List::Util
or List::MoreUtils
. Both contain an any
call which acts as a short-circuiting grep
. Alternatively, if you are trying to implement the ARRAY1 ARRAY2
option, the later library contains a pairwise
call that may serve.
Upvotes: 6
Reputation: 57630
Just spell out what you mean. E.g. if you want to check whether the header line matches any regex in @patterns
:
use List::Util 'any';
...
my $line = <F>;
if (any { $line =~ $_ } @patterns) { ... }
Though in that case, it might be more sensible to pre-compile a single pattern such as:
my ($pattern) = map qr/$_/, join '|', @patterns;
...
if (<F> =~ $pattern) { ... }
If your @patterns
array contains different kinds of data, you might want to choose a different matching operator, e.g. ==
or eq
. If the @patterns
are not all the same “type” and you really want the smartmatch behaviour, you can silence the warning and continue to use it:
use experimental 'smartmatch';
However, this might then break without further warnings in the future.
Upvotes: 9