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.