DEV Community

Toby Inkster
Toby Inkster

Posted on • Originally published at toby.ink on

5

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 ) {
        ...;
    }
Enter fullscreen mode Exit fullscreen mode

For those who don't like the infix syntax, a regular function is also provided:

    use match::simple 'match';

    if ( match $this, $that ) {
        ...;
    }
Enter fullscreen mode Exit fullscreen mode

Its behaviour was always determined by the operand on the right-hand side. Given:

    $a |M| $b
Enter fullscreen mode Exit fullscreen mode
  • 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 } ) {
        ...;
    }
Enter fullscreen mode Exit fullscreen mode

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 ) {
        ...;
    }
Enter fullscreen mode Exit fullscreen mode

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 ) {
        ...;
    }
Enter fullscreen mode Exit fullscreen mode

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 ) {
        ...;
    }
Enter fullscreen mode Exit fullscreen mode

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.

Speedy emails, satisfied customers

Postmark Image

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs