Something cool about Perl 6 every day

Primary Menu

Day 14 – nextsame and its cousins

Maybe you’re familiar with the way the keyword super in Java allows you to delegate to the method (or constructor) of a base class. Perl 6 has something similar… but in a world with multiple inheritance and mixins it makes less sense to call it super. So it’s called nextsame. Here’s an example of its use:

row, row, row your boat,
gently down the stream.
merrily, merrily, merrily, merrily,
life is but a dream.

You’ll note how the call finds its way from C.sing via B.sing over to A.sing. Those transitions are (of course) mediated by the nextsame calls. You’ll note the similarity to, for example, Java’s super.

But calling along the inheritance chain is not the only place where nextsame proves useful. Here’s an example not involving object orientation:

So that’s another reason nextsame is not called super: it’s not necessarily related to the base class, because there might not be a base class. Instead, there’s some more general phenomenon involved. What might that be?

Every time we do a call to something, there’s a part of the language runtime making sure that the call ends up in the right routine. Such a part is called a dispatcher. A dispatcher makes sure that the following multi call ends up in the appropriate routine:

(And a nextsame in the second multi foo would re-dispatch to the first. But that doesn’t work in Rakudo yet.)

Dispatchers are everywhere in Perl 6. They’re involved in method calls, so that a method can defer along the inheritance chain, as we did in the beginning of the post. They’re in wrapped routines, so that the code doing the wrapping can call into the code being wrapped. And they participate in multi dispatch, so that multi variants can defer to each other. It’s all the same principle, but in different guises.

And nextsame is just a way to talk directly to your friendly neighborhood dispatcher. By the way, the keyword is called nextsame because it instructs the dispatcher to defer to the next candidate with the same signature. There are variants, as you’ll see below.

Though pretty cool, this use of nextsame isn’t really anything new; in fact it’s just another example of the defer-along-the-OO-callchain dispatcher. That’s because mixing in the role LogFoo with but causes an anonymous subclass to be created, one that also does LogFoo. So role mixin nextsame boils down to just inheritance nextsame. (But we don’t need to actually grok that to use it, and it still feels slightly magical and very nice to use.)

In summary, nextsame works in a lot of places you’d expect it to work, and it works the way you expect it to. It defers to the next thing.

Oh, and nextsame has three closely related cousin keywords:

nextsame Defer with the same arguments, don't return
callsame Defer with the same arguments, then return
nextwith($p1, $p2, ...) Defer with these arguments, don't return
callwith($p1, $p2, ...) Defer with these arguments, then return

Naturally, the other three can be used in the same situations nextsame can.

“Module inheritance” is a bit of an oxymoron, since inheritance is a relation between classes, and becomes expressed through the dispatching of methods. A module of subs is twice removed from such action.

I tried the above in Rakudo. It doesn’t work, but to my surprise the ‘module B is A’ declaration didn’t throw a Big Fat Error. I think it should (to catch misunderstandings like this early), so I submitted a rakudobug about it.