Reputation: 1807
In Perl, using Moo
, you can implement around
subs, which will wrap around other methods in a class.
around INSERT => sub {
my $orig = shift;
my $self = shift;
print "Before the original sub\n";
my $rv = $orig->($self, @_);
print "After the original sub\n";
};
How can this behaviour be implemented in Raku, preferably using a role
?
Upvotes: 14
Views: 269
Reputation: 5072
Implements before(), after() and around() functions that can be used to modify class methods similarly to Perl 5's Moose. It uses wrap() internally, and returns the wrapper handler, so it is easy to .restore() the original.
This is how the module implements around
:
sub around ($class, $method-name, &closure) is export
{
$class.^find_method($method-name).wrap(method { closure(); });
}
Upvotes: 8
Reputation: 23517
Use wrap
sub bar () { return "baþ" };
my $wrapped = &bar.wrap( { " → " ~ callsame() ~ " ← " } );
say bar(); # OUTPUT: «→ baþ ← »
Since methods are routines, you'll need a slightly more convoluted way to get a handle on the method itself, but other than that, the method is exactly the same, since Method
s are a subclass of Routine
s
class Baz {
method bar () { return "baþ" };
}
my &method_bar = Baz.^find_method("bar");
my $wrapped = &method_bar.wrap( { " → " ~ callsame() ~ " ← " } );
say Baz.bar(); # OUTPUT: «→ baþ ← »
The $wrapped
is a handle that can be used, later on, to unwrap it if needed.
Edit: to add the code to get a handle on the class method, taken from here, for instance.
Upvotes: 6
Reputation: 5726
You can shadow the method with the role and then use callwith
:
class Foo {
method meth { say 2 }
}
my $foo = Foo.new but role :: {
method meth(|c) { say 1; callwith(|c); say 3 }
};
$foo.meth
Upvotes: 8