Skip to content

Instantly share code, notes, and snippets.

@robertlemmen
Last active April 24, 2018 13:38
Show Gist options
  • Save robertlemmen/13b62797ff0ef312b7efa9d48fb8e966 to your computer and use it in GitHub Desktop.
Save robertlemmen/13b62797ff0ef312b7efa9d48fb8e966 to your computer and use it in GitHub Desktop.

A less Stern Look of Disapproval

A while ago a great person callen Karen wrote a Perl 5 Module called Acme::LookOfDisapproval (http://search.cpan.org/~ether/Acme-LookOfDisapproval-0.006/lib/Acme/LookOfDisapproval.pm). It allows you to use a well known and visually clear character sequence instead of the somewhat cryptic Perl "warn" method:

    ಠ_ಠ 'cannot handle request due to missing foobricator';

While this module probably has not found it's way into too many production systems, I want to argue that it is a very useful module line-for-line:

For a start it has exposed a couple of bugs and weirdnesses in all sorts of systems that handle Perl 5 modules. But more importantly it raises interesting questions about how a language can allow and support modification and extension of "core" features that are deeply entangled with concepts like exception handling. And it teaches a great many things about how Perl 5 really works.

So it is only natural that this module must be re-implemented in Perl 6 to see if similarily interesting effects turn up! The good, or boring, news is that the implementation is quite straight forward and pretty much free of magic:

sub ಠ_ಠ(*@message) is hidden-from-backtrace is export {
    warn @message;
}

So there you are. One interesting bit is the "hidden-from-backtrace". As it turns out this is a trait modifier (https://docs.perl6.org/type/Sub#index-entry-trait__mod_%28declarator%29), and while this looks like some special case in the language (the "is export" even more so), it is pretty much free of magic. Interestingly it is not an annotation like some Java folks would expect, and it is not through reflection in the traditional sense that this is used when printing the backtrace. Instead the trait actually modifies the routine that it was invoked on. Perhaps the following, also highly useful, example illustrates this point:

multi sub trait_mod:<is>(Routine:D $r, :$broken!) {
    $r.wrap({ warn "broken sub $($r.name.perl)!!!"; callsame; });
}

sub holler() is broken {
    say "woohoo";
}

holler;

And while this sort of aspect-oriented programming needs to be used with some restraint, it is a great example of how Perl 6 manages to build generic and simple yet powerful mechanisms into the core language, and then leverages them at higher levels to implement language features (like the backtrace or export management) without the usage of any voodoo or special cases.

A similar topic to look at would be how the underlying exception behind "warn" manages to resume at the point it was thrown (call/cc anyone?), but one thing at a time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment