All this Haskell programming has opened my eyes to what our multimethod
dispatch could be.  As we have seen with C<sort>, the dispatch system is
a pattern matcher.  But it's a pretty terrible one. 

I think we should replace our multimethod system with a more general
pattern matcher, a "variadic multimethod" system of sorts.  Multimethods
need to be variadic anyway, because we want pugs's quicksort example to
work.

Here's my proposal:

Inside an argument list, the first mention of a variable introduces its
binding.  Later arguments require a match.  We can now define 'equal':

    sub equal ($x, $x) { 1 }
    sub equal ($x, $y) { "" }

That's one of the MTOWs at least.  The evaluation order of the patterns
still needs to be thought out.

There are more types of patterns.  Types are patterns, and from this we
see that following a pattern by a variable binds the variable to
whatever matched that pattern.  Constants are also patterns.  Junctions
of patterns are also patterns.  Lists of patterns are patterns, as are
hashes of patterns.  In fact, the last two give us slurpy scalars:

    sub length () { 0 } 
    sub length (*[ $x, [EMAIL PROTECTED] ]) { 1 + length @rest }

And +$name parameters:

    sub length (*{ name => $name }) { }

C<where> constrains a pattern:

    sub factors ($x where { is_prime($x) }) { $x }
    ...

(The object in question is given as the topic of the where block:

    sub factors ($x where { .is_prime }) { $x }
    ...

)

There will also be hooks to allow arbitrary pattern objects.

    # does $x match our pattern?
    method Pattern::MATCHES ($x) { ... }

And now here's the cool part.  A type is defined to be a pattern (a
'class' is different, though, but it creates an identically-named type).
So instead of definining these multis (I seek to banish the 'multi'
keyword, since I seek to banish the idea of an invocant), you could also
pretend that they're methods on subtypes.  A 'role' is just a collection
of methods on a type, a pattern:

    role ($x where {.is_prime}) {
        method factors() { $?SELF }
    }

This is exactly equivalent to:

    sub factors($x where {.is_prime}) { $x }

And of course, if you define a role with a name, then it becomes an
"abstract type":

    role Serializable {
        method serialize() {...}
        method clone() { restore(.serialize) }
    }

And you have to tell objects that they're Serializeable. 

Luke

Reply via email to