Skip to content

Instantly share code, notes, and snippets.

@sycobuny
Created April 26, 2012 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sycobuny/2499830 to your computer and use it in GitHub Desktop.
Save sycobuny/2499830 to your computer and use it in GitHub Desktop.
use v5.14;
use warnings;
package PackageA {
# put subs in here and then coderefs passed to PackageA->configure() can use these methods
# as though they're in the right package
package PackageA::ConfigurationSubs {
sub hello {
say "hello, world";
}
}
sub configure {
my ($package, $coderef) = @_;
my ($in) = caller;
# fetch the symbol table stash for the configuration subs
my (@symbols) = keys %PackageA::ConfigurationSubs::;
# copy the methods from PackageA::ConfigurationSubs to the package that
# called us
for (my $x = 0; $x <= $#symbols; $x++) {
no strict 'refs';
my ($symbol) = $symbols[$x];
# this is where the subref lives, probably.
my ($glob) = *{"PackageA::ConfigurationSubs::$symbol"};
# if there's a subref, localize an alias in the remote package
local(*{"$in\::$symbol"}) = *$glob{CODE} if (*$glob{CODE});
# we have to call the coderef in this funky way because otherwise
# our local()ization of those subs goes away.
if ($x == $#symbols) {
$coderef->();
}
}
}
}
package PackageB {
our (@ISA) = qw(PackageA);
__PACKAGE__->configure(sub {
hello(); # calls PackageA::ConfigurationSubs::hello();
});
# hello(); <- this would generate an error right here.
}
use v5.14;
use warnings;
package PackageA {
sub hello {
say "hello, world";
}
}
package PackageB {
sub configure {
my ($coderef) = sub {
hello;
};
...
# is there a way in the ... for me to call $coderef as though it were declared in
# PackageA? that is, I want, essentially, $coderef->(); to output "hello, world", not
# give me an "Undefined subroutine &PackageB::hello" error.
}
}
@sycobuny
Copy link
Author

Note that I don't really have to call the coderef in the yadda-yadda, and in my eventual real-world case which is more complicated, I'd probably call it either completely outside either package, or inside PackageA.

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