Categories

Posts in this category

Thu, 12 Apr 2012

Rakudo Hack: Dynamic Export Lists


Permanent link

Rakudo's meta programming capabilities are very good when it comes to objects, classes and methods. But sometimes people want to generate subroutines on the fly and use them, and can't seem to find a way to do it.

The problem is that subroutines are usually stored (and looked up from) in the lexical pad (ie the same as my-variables), and those lexpads are immutable at run time.

Today I found a solution that lets you dynamically install subroutines with a computed name into a module, and you can then use that module from elsewhere, and have all the generated subroutines available.

module A {
    BEGIN {
        my $name = 'foo';
        my $x = sub { say 'OH HAI from &foo' }
                but role { method name { $name } };
        trait_mod:<is>(:export, $x);
    }
}

Inside the module first we need a BEGIN block, so that the is export trait will run while the module is being compiled, and thus knows which module to associate the subroutine to.

Next comes the actual code object that is to be installed. Since the export trait inspects the name of the subroutine, we need to give it one. Doing that dynamically can be done by overriding the name method, here by mixing in a role with such a method into the code object.

Finally comes the part where the export trait is applied. The code here uses knowledge of the calling conventions that hide behind a trait.

A different script can then write

use A;
foo();

And access the dynamically exported sub just like any other.

In future there will hopefully be much nicer APIs for this kind of fiddling, but for now I'm glad that a workaround has been found.

[/perl-6] Permanent link