Thats a side effect of how its implemented.
When you use a method modifier, they basically replace the existing method with a new one, and the new one contains a reference to the old.
So when you see
before foo => sub {
}
What happens at role composition time is:
my $orig = *package::foo;
*package::foo = sub {
$beforetrigger->( @args );
return $orig->( @args );
}
More or less.
So imagine, you have 2 subs, "A", the version of BuildMenu that gets invoked before applying the role, and "B", the version of BuildMenu that gets invoked after applying the role.
So what happens, is your calling order pans out like this:
First Call ->
A ->
before ->
apply roles ->
replace A with B
<-- return from before
A body ->
<-- return from A Body
Subsequent Call
B -> something
Etc, so, what I think you need to do, is have your wrapping code acknowledge this, and pass control over after application.
around foo => sub {
my ( $orig, $self , @args ) = @_;
# apply role to $self here
# this gets the sub that will be resolved *after* the role is applied
my $wrapped_sub = $self->can('foo');
my $rval = $wrapped_sub->( $self, @args );
return $wrapped_sub->( $self, @args );
}
Note there's the potential for that code to have a fun thing where $wrapped_sub is the sub I just wrote to apply the roles, ... I haven't worked out exactly what will happen there yet, but you may need to put in some conditions to prevent a self-calling-sub death loop from occurring.
But the gist of the problem essentially boils down to the fact you can't replace a sub that is executing, with a new sub, from the sub itself, and expect it to daisy chain automatically, Because the sub being replaced is not inherently aware of it being replaced, and because "method modifiers" amount to replacing subs with new ones that chain to old ones =)