2

Consider a string, like a response header: HTTP/1.1 404 Not Found.

I'm curious if you could use the combination of the smartmatch (~~ or double tilde) operator and regex to search for incomplete, or a subset, of matches.

my $head    = q{HTTP/1.1 404 Not Found};
my @success = (200, 201);
my @failure = (404, 409);

# Array First
say q{Success} if @success ~~ $head;
say q{Fail}    if @failure ~~ $head;

# Array Second
say q{Success} if $head ~~ @success ;
say q{Fail}    if $head ~~ @failure ;

I know this could be done with some sort of looping, grep, or map; but I am checking into the possibilities of what the ~~ can and can't do.

The documentation is pretty descriptive and for the majority of lhs/rhs conditions seems to follow a return true for an [all in left side] == [all in right side] evaluation.

That said, if $head is just the number (eg $head=q{200}) it would match.


The expected result would be similar to:

my $head      = q{HTTP/1.1 201 OK};
my @success   = qw(200 201);
say q{Success} if grep{$head =~ /$_/ } @success;
vol7ron
  • 40,809
  • 21
  • 119
  • 172
  • 8
    The smart match operator has, unfortunately, been [re-declared experimental in 5.18.0](https://metacpan.org/module/RJBS/perl-5.18.0/pod/perldelta.pod#The-smartmatch-family-of-features-are-now-experimental) and now throws warnings. Given it's continuing instability, and its behaviors will likely change, I would recommend against using it. – Schwern May 30 '13 at 19:05

1 Answers1

1

As Schwern previously pointed out, the smart-match operator is currently marked as experimental/deprecated[1], so switching to the smart-match operator is not recommended.

Besides, it's probably better to build a regex anyway.

my @success = (200, 201);
my @failure = (404, 409);

my $success_pat = join '|', map quotemeta, @success;
my $failure_pat = join '|', map quotemeta, @failure;

my $success_re = qr/$success_pat/;
my $failure_re = qr/$failure_pat/;

say q{Success} if $head =~ $success_re;
say q{Fail}    if $head =~ $failure_re;

  1. There's always been discord of what each specific THING ~~ THING should do, so Perl is moving to something clearer, possibly something like Smart::Match's THING ~~ FUNC(THING) approach.
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • Was originally going to do that, was hoping that the smartmatch would be smartmatchical :] but as Schwern pointed out it's probably a bad idea – vol7ron May 31 '13 at 14:47
  • and slower if you're going to do it more than once. – ikegami May 31 '13 at 19:25
  • smartmatch? or grep? I'm guessing one regex (by joining the array) would be faster, especially if sorted by most likely to be matched, first. – vol7ron May 31 '13 at 21:08
  • Reapetedly comparing up to N strings will be slower repeatedly trying to match against 1 regex. Since 5.10, a trie will be created from the alternation, so it's very fast. Sorting won't help much if at all. – ikegami May 31 '13 at 21:23
  • Agreed on first point; regarding sorting, I was thinking that it would return at first match, thus if the first option in an array (one small regex) matches the string, it won't continue to evaluate the rest of the array elements (for smartmatch). The sorting w/in a regex matters less, depending on the complexity of the regex option (and the regex engine's order-of-operations). – vol7ron Jun 01 '13 at 17:01
  • Basically, `/200|201/` becomes an efficient version of `/20(?:0|1)/` – ikegami Jun 01 '13 at 17:43
  • Is that first re right; does the alternative operator work in bare code like that -- I was thinking it would be `/(?:200|201)/`. Also, I'll probably end up selecting this as the answer, since it's the only answer, though I think Schwern's comment was more pertinent to the smartmatch. – vol7ron Jun 01 '13 at 19:11
  • Is `/200|201/` correct? For sure! I can add the smart-match comment to my answer, if you wish.. – ikegami Jun 01 '13 at 19:19
  • General remark: When matching numbers in strings, the "patterns" (like in `@success`) should be strings, too. Maybe also the answer should use something similar to `map quotemeta " $_ ", @success` instead of `map quotemeta, @success`. OK, it's guessing, but the exact scenario is not described any better. – U. Windl Aug 26 '21 at 07:10