I need to wrap a sub so that it can trigger before/after events before returning its original return value. Everything works except if the coderef returns an array it will be cast to an arrayref. Sometimes I do want an arrayref so I can't just check the ref type and recast to an array. I've also tried using wantarray which is still returning an arrayref.
I'm currently trying to go about it like this
$owner->methods->each(sub { # Methods is a hash container where each entry is a mapping of a method name to its implementation (as a coderef)
my ($key, $val) = @_;
return if $key eq 'trigger' || $key eq 'triggerBefore' || $key eq 'before' || $key eq 'on'; # Ignore decorating keys that would cause infinite callbacks
$owner->methods->set($key, sub { # Replace the original sub with a version that calls before and after events
my ($obj, @args) = @_;
$owner->triggerBefore($key, @args);
my $return = $val->(@args); # Return could be anything...
$owner->trigger($key, $return);
return $return;
});
});
I've also tried replacing the return with the following to no avail:
return (wantarray && ref $return eq 'ARRAY') ? @$return : $return;
Everything works fine if I don't store the return value and instead return $val->(@args); (but then I lose the "after" trigger). Is there a way to store the return value "as is" rather than storing it in a scalar?
Contextual::Returnmight be worth a look