Created
April 26, 2012 14:02
-
-
Save sycobuny/2499830 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.