I propose that we remove the following two lines from the smart match
table in S03:

   Hash    Any       hash entry existence     exists $_{$x}
   Array   Any       array contains item*     any($_) === $x

These are the two lines with Any on the right side.  I want to remove
these so that we can have an extensible ~~ operator.

You can think of $x ~~ $y as saying "$x matches $y", i.e. $y is some
data pattern and we are asking if $x conforms to it.  I want to be
able to add my own kinds of patterns, and entries with Any in the
right side undermine this.

Why?  Let's say I created a pattern  which implemented another textual
matcher alongside Perl's regexes, which was more convenient for some
things (I shouldn't have to convince you that this is possible and
useful).  Let's call it Irregex.  I want it to work just like Perl's
regexes; i.e. I want it so that if you ask whether an array matches
it, it will match against the elements of the array as though they
were characters.  So I just overload ~~ to work on (Array, Irregex)
and that overrules (Array, Any) so there is no MMD ambiguity.

However!  Let's say I'm using a payroll library (or something, sorry
for the mundane examples; I'm trying to keep it realistic) which sends
a notification if any user's status matches a pattern, and it is
implemented like so:

   method notify(Any|Junction $pattern) {
       if @.users>>.<status> ~~ $pattern {
           # send notification
       }
   }

This is perfectly fine, elegant code given the ~~ table.  But it
breaks since we have added our new pattern type!  It doesn't check if
any user's status matches, it checks if the users' statuses'
concatenated considered as atoms matches, totally wrong!

So, I'm essentially asking for ~~ to be singly-dispatched based on its
right argument, which gets to pick how to interpret the left one.  In
order to encourage this usage, I propose a design like so:

   role Pattern {
       method match($item) {...}
   }
   # Code, Bool, Undef, Whatever, Num, Junction, Str, Hash, ... ...
all do Pattern

   sub *infix:<~~> ($item, Pattern $pat) {
       $pat.match($item);
   }

So to add a new pattern, you just implement the Pattern role, and you are safe.

If you are very attached do those two rows of the smart match table,
we can reimplement them as Pattern objects, at the expense of some
unreadability:

   given @array {
       when 42 { ... }
   }

Becomes:

   given @array {
       when contains 42 { ... }
   }

etc.

Luke

Reply via email to