What to use instead of Smartmatch?
Asked Answered
L

4

8

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?

Libelous answered 19/4, 2018 at 12:24 Comment(2)
You can add use experimental 'smartmatch' see metacpan.org/pod/experimental for more informationProtamine
Remarkable timing. 5.26.2 came out about a week ago. 8DFoxhound
L
9

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.

Lofton answered 19/4, 2018 at 14:1 Comment(2)
I have update OP with the regex that @patterns contain. The reason to pre-compile, is that because of performance? I would prefer your any example as it would be easier to understand in later on.Libelous
@SandraSchlichting If you find any or grep easy to understand, use that. Readability is important. Yes, pre-compiling the regex might be a bit more efficient since the alternatives can be checked within the regex engine, without having to execute any Perl code. Note that your second pattern matches anything that the first pattern would match. They only differ in case you access the captures.Lofton
F
6

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.

Foxhound answered 19/4, 2018 at 14:3 Comment(1)
I have updated the OP and yes, @patterns are regex's =) grep would be perfect, as it is easy to understand in a year from now.Libelous
S
2

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

Ster answered 18/1, 2019 at 19:16 Comment(0)
C
0

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.

Cassation answered 10/3, 2023 at 17:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.