Threaded Values

In my constant struggle to find the Grand Unified Multimultimethod Paradigm (GUMP?), I started to think about how Perl 6’s Junctions interact. Junctions really aren’t multimethod candidates at all. They’re a special type of “meta-value” which implicitly take over all operations on them. And that type of value turns out to be a lot more useful than just to implement Junctions. And so I think we should generalize it, to make a generic autoöverload hook.

As an interesting example, we could implement the generalized Einstein notation (as Synopsis 9 proposed, and everybody liked the idea, but nobody liked the solution). The index could be an autoöverloading value that computes its necessary range and then evaluates at all the values it needs to.

The actual rules of Einstein notation are pretty yucky when you’re dealing in a practical context (it has to do with summing over things that appear exactly twice). But it’s easy to generalize, even away from sums. Then you could do the matrix multiplication yj = Aijxi like so:

    use Notation::Einstein;
    ein -> $j { @y[$j] = esum { @A[$j;$^i] * @x[$^i] } }

Which is probably as good as it’s going to get without introducing special case rules.

Now let’s think about how the autoöverload method works. It’s powerful enough to support Junctions, which ought to be as much power as we’re ever going to need out of it. Bascially, anything you do with it at runtime can be intercepted. Pass it to a function, add something to it, flirt with it, whatever, it knows.

For efficiency, I’d suggest that these guys deserve a declaration or a secondary sigil so the compiler can see them. Junctions would have it too (I’ve gradually been convincing myself that this would be a good idea on a language level as well). It’s like a fancy tie, so I’ll call it $~thing.

Here’s where the multimethods come in. It’s not multi infix:+ (Junction $~j, $x) as you might expect, but rather multi OVERLOAD (Junction $~j: Operator &o: *@_) (or something like it). Using subtype-based dispatch, you can be as specific as you like with the operator (any operator, any infix operator, the plus operator, any sub call, etc.). Operator is a very generic, interesting type, and I’ll leave the discussions of that to the insane ramblings inside my own head… which occasionally make it to this page.

So this multimethod allows you to specify exactly what you want to intercept—how local you want your object to be. If you try to alias your object non-tiddily object, you either get an error or you run the risk of your semantics not propagating (I can’t decide). In any case you could always overload :=. Anyway, here’s the OVERLOAD method for a conjunction.

    multi OVERLOAD (Conjunction $~j: Operator &o: *@_) {
        Conjunction.new([
            map { &o($_, *@_) } $~j.real.states  # .real keeps the junction from intercepting the call
        ]);
    }
    multi OVERLOAD (Conjunction $~j: Operator::Boolify: *@_) {
        grep { ?$_ } $~j.real.states
    }
About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s