'before' and 'after' modifiers can be done declaratively. But may need some meta-programming extensions.
I've done a first cut at a basic solution. Module CLOS defines before and after method traits as below:
use CLOS;
class Bake {
method preheat {
say "preheating";
}
method cook {
say "cooking";
}
method rest {
say "resting";
}
}
class Cook is Bake {
method preheat is before {
say "...about to preheat";
}
method rest is after {
say "...resting done";
}
}
my $cook = Cook.new;
$cook.preheat;
say "----";
$cook.cook;
say "----";
$cook.rest;
Produces:
perl6 -I . Bake.pm
...about to preheat
preheating
----
cooking
----
resting
...resting done
Contents of CLOS.pm follow:
This approach combines:
1. traits
Traits — Meta Data With Character (moritz, 2011)
2. class meta-programming
Adventures in writing a simple grammar profiler (perlpilot, 2011) (adapted from grammars to classes)
3. Object hashes
Object Hashes (Brian D Foy, 2016)
my class CLOSClassHOW is Metamodel::ClassHOW {
my Bool %before{Any};
my Bool %after{Any};
multi sub trait_mod:<is>(Routine $r, :$before!) is export {
%before{$r} = True;
}
multi sub trait_mod:<is>(Routine $r, :$after!) is export {
%after{$r} = True;
}
#| find this method in our parents
method !find-super-method($obj, $name, *@etc) {
my @mro = self.mro($obj);
@mro.shift; # skip ourselves
for @mro {
my %methods = $_.HOW.method_table($_);
return %methods{$name}
if %methods{$name}:exists;
}
}
method find_method($obj, $name) {
my $raw-meth := callsame;
my $meth := $raw-meth;
if $raw-meth.defined && (%before{$raw-meth} || %after{$raw-met
+h}) {
my $next-meth := self!find-super-method($obj,$name);
$meth := -> $c, |args {
$raw-meth($obj, |args) if %before{$raw-meth};
my $result := $next-meth($obj, |args)
if $next-meth.defined ;
$raw-meth($obj, |args) if %after{$raw-meth};
$result;
}
}
$meth;
}
method publish_method_cache($obj) {
# no caching, so we always hit find_method
}
}
my module EXPORTHOW { }
EXPORTHOW.WHO.<class> = CLOSClassHOW;
Basically we define traits
before and
after which collect the routines to be wrapped in object hashes
%before and %after.
The ClassHOW meta-class is extended to interpret the `before` and after traits, invoking a super method located with the
!find-super-method private method.
This could possibly be fleshed out into a Perl 6 module.