Day 12 – Smart matching

Remember the https://perl6advent.wordpress.com/2010/12/04/the-sequence-operator/ sequence operator? As the last argument it takes a limit, which makes the sequence generation stop. For example:

    1, 2, 4 ... 32;         # 1 2 4 8 16 32
    1, 2, 4 ... * > 10;     # 1 2 4 8 16

You can see that in the first case, numerical equality is used. The second is a bit more interesting: * > 10 is internally rewritten into a closure like -> $x { $x > 10 } (through currying).

The sequence operator then does some magic comparison, depending on the type of the matcher. This comparison is called "smartmatching", and is a concept that reappears in many places in Perl 6. Examples:

    # after the 'when' keyword:
    given $age {
        when 100    { say "congratulations!"      }
        when * < 18 { say "You're not of age yet" }
    }
    # after 'where':
    subset Even of Int where * %% 2;
    # with an explicit smartmatch operator:
    if $input ~~ m/^\d+$/ {
        say "$input is an integer";
    }
    # arguments to grep(), first() etc.:
    my @even = @numbers.grep: Even;

On the right-hand side of the ~~ operator, and after when and where, the value to be matched against is set to the topic variable $_. This allows us to use constructs that operate on $_, like regexes created with m/.../ and .method_call.

Here is what the smart match operator does with some matchers on the right-hand side:

    # is it of type Str?
    $foo ~~ Str
    # is it equal to 6?
    $foo ~~ 6
    # or is it "bar"?
    $foo ~~ "bar"
    # does it match some pattern?
    $foo ~~ / \w+ '-' \d+ /
    # Is it between 15 and 25?
    $foo ~~ (15..25)
    # call a closure
    $foo ~~ -> $x { say 'ok' if 5 < $x < 25 }
    # is it an array of 6 elems in which every odd element is 1?
    $foo ~~ [1, *, 1, *, 1, *]

The full table for smart matching behavior can be found at
http://perlcabal.org/syn/S03.html#Smart_matching.

Notice how, unlike in Perl 5, in Perl 6 smartmatching is the only syntactic way to match a regex, it has no special operator. Also, while most smart matching cases return a Bool, matching against a regex returns a Match object – which behaves appropriately in boolean context too.

You have probably started wondering: a’right, that for built-in types, how do I use it in my own classes? You need to write a special ACCEPTS method for it. Say we have our good, old class Point:


    class Point {
        has $.x;
        has $.y;
        method ACCEPTS(Positional $p2) {
            return $.x == $p2[0] and $.y == $p2[1]
        }
    }

Everything clear? Let’s see how it works:

    my $a = Point.new(x => 7, y => 9);
    say [3, 5] ~~ $a; # Bool::False
    say (7, 9) ~~ $a; # Bool::True

Perl 6 can now do exactly what you mean, even with your own classes.

2 thoughts on “Day 12 – Smart matching

  1. I think you mean ‘smartmatch’ rather than ‘smartmath’ about 3/4 of the way down.

    But it’s an interesting pun, given the discussion of autogenerated sequences like 1, 2, 4 … 32;

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.