I think the closest things we've got to pattern matching come from a
combination of multiple dispatch, where clauses and signature
unpacking. I don't know much about the latter, but a where clause can
discriminate multiple dispatch variants based on parameter values
rather than just the type, so you can say:
multi doSomething(@a where { .elems == 0 }) {
# empty arrays only
}
multi doSomething(@a where { .elems >= 3 && .[2] == 4 }) {
# arrays with a third element numerically equal to 4
}
multi doSomething(@a) {
# anything else
}
Which is pretty powerful, really.
> This is a contrived example of what I'm referring to:
>
> sub traverse([Leaf $a]) {
> # do something
> }
>
> sub traverse([Tree $left, Tree $right]) {
> traverse($left);
> traverse($right);
> }
>
> my $t = Tree(...);
> traverse($t);
You could do most of this with multidispatch and where clauses. It
doesn't quite work because of the unpacking which pattern matching
does, and also because Perl 6 data structures don't get built in the
same way that Haskell ones do, and you've used a Haskell-like syntax
for Leaf and Tree and so forth.
Now, while it might be nice to say let me write a signature which
accepts a Tree object which has a left and right subtree, and binds
them to $left and $right respectively, arguably a where clause can
check that the subtrees exist, and your tree class should have good
accessors for the subtrees which make unpacking them a little
pointless. This is where Perl 6 is not the same as functional
languages, since it's got an imperative OO element as well.
multi traverse(Tree $t where { all(.left, .right).defined }) { ... }
Perhaps.