objectmetaprogrammingrakurakudometa-object-protocol

Using EXPORTHOW to make declarator that acts like "sub"


The excellent 2011 Advent of Raku post Meta-programming: what, why and how provides a few clear examples of using EXPORTHOW to create a declarator that acts like class. Here's the first:

my class SingleInheritanceClassHOW
    is Metamodel::ClassHOW
{
    method add_parent(Mu $obj, Mu $parent) {
        if +self.parents($obj, :local) > 0 {
            die "Multiple inheritance is forbidden!";
        }
        callsame;
    }
}
my module EXPORTHOW { }
EXPORTHOW.WHO.<class> = SingleInheritanceClassHOW;

Is there a way to do something similar for a declarator that acts like sub (that is, that allows the use to supply a signature and block, rather than allowing the user to supply attributes and methods)? The metaclass of a Sub is ClassHOW, so it seems that something similar should be possible, but I'm not seeing a way to do so.


Solution

  • The EXPORTHOW mechanism is only for overriding the metaclass that will be used for package declarators, with the slight extension that EXPORTHOW::DECLARE also performs a grammar tweak that introduces a new package declarator.

    While one can call .HOW on a Sub, the result does not relate to the subroutine itself, but rather the metaclass of the Sub type, of which a subroutine is an instance.

    Really, EXPORTHOW is an "easy things easy" mechanism (to the degree it's fair to call anything relating to meta-programming easy!) It was also a straightforward thing to provide: the parsing of package declarations was already extremely regular, and the compiler already maintained a mapping table from package keyword to metaclass, so providing a way for a module to replace entries in that table (or add new ones for DECLARE) was barely a few hours of compiler hackery.

    Routines are vastly less regular, even if that's only somewhat apparent syntactically. While packages pretty much parse the keyword (class, role, grammar, etc.) and what follows is the very same syntax and semantics for all of them (modulo roles permitting a signature), there are separate parse rules and semantics behind each of sub, method, macro, and rule. Their interaction with the overall compilation process is also rather more involved. The ongoing RakuAST effort is bringing a bit more order to that chaos, and ultimately - when coupled with slangs - will offer a way to introduce new sub-like constructs, as well as to give them semantics.