Matching simply
A little over ten years ago, when Perl 5.18 was approaching its release date, I released match::simple. This was mostly in response to the smartmatch operator (~~
) being deprecated, but also a solution to the incredibly arcane rules for how the smartmatch operator operated.
match::simple was intended to be... simpler. The operator looks a little funky because it uses some clever trickery to fake being an infix operator:
use match::simple; if ( $this |M| $that ) { ...; }
For those who don't like the infix syntax, a regular function is also provided:
use match::simple 'match'; if ( match $this, $that ) { ...; }
Its behaviour was always determined by the operand on the right-hand side. Given:
$a |M| $b
- If
$b
is undef,$a
only matches if it's also undef. - If
$b
is any other non-reference value, acts like the string equality (eq
) operator. - If
$b
is a regexp, acts like the regexp binding (=~
) operator. - If
$b
is a coderef,$a
matches if$b->($a)
returns true. - If
$b
is an object,$a
matches if$b->MATCH($a)
returns true or$a ~~ $b
using~~
operator overloading. - If
$b
is an arrayref,$a
matches if$a |M| $_
for any element of@{$b}
. - If
$b
is anything else, the operator croaks.
These seemed simple, sane, and predictable. Yes, some form of numeric matching would have been nice, but I ruled that out because of the ambiguity of numeric strings.
Plus because if you really need numeric matching, I knew you could wrap the number in a coderef:
if ( $a |M| sub { $b == shift } ) { ...; }
Type::Tiny has always been compatible with match::simple. You can use:
use match::simple; use Types::Standard -types; if ( $value |M| ArrayRef ) { ...; } elsif ( $value |M| HashRef ) { ...; }
Anyway, fast forward to now, and Perl 5.38 has now been released, which finally removes the long-deprecated smartmatch operator. Thankfully one of the new features it also provides allows for true user-defined infix operators!
Introducing Syntax::Operator::Matches!
use Syntax::Operator::Matches; if ( $this matches $that ) { ...; }
This uses exactly the same logic as match::simple — logic that has been frozen since 2013, but finally has beautiful syntax.
You can do nice things like:
use Syntax::Operator::Matches; use Types::Standard -types; if ( $value matches ArrayRef[Int] ) { ...; } elsif ( $value matches Str|Undef ) { ...; }
Some of it is just a wrapper around match::simple, but other parts happen purely in XS, so operate much faster.
If you're looking for something to replace smartmatch in your code, consider Syntax::Operator::Matches. If you need backwards compatibility, match::simple is still here and isn't going to disappear.
Nice, looks ideal for Olaf's advent calendar.
I agree. Looks like it builds on your Sub::Infix, which I think is a great module. I encourage everyone to study its implementation.