How can I import Perl code from external files at compile time?
Help Perlers! Does anyone know a simple "insert code here" approach would bring code from external files once at compile time into a package?
Background:
I have a standard PBP-style inside-out class that is getting quite large. I want to split the code into multiple files but not extend the class. Optimally, I would simply insert the code into the "Magic JuJu" section of the example module (see below) once at compile time.
I have looked at AutoLoader as a means to get this accomplished. However, there are two things that give me pause. If I could get around these, it might be a near-optimal solution:
I don't want to split every little sub into a separate file; just a few more reasonably sized files (using sub stubs in the caller is fine, though); and
I don't want to defer compile on every sub; some subs I'd like to have compiled on initial use. However, this is probably not a deal breaker.
I know Moose provides "Roles", which I believe does this well, but for various reasons, Moose is not an option for this project, nor is Mouse.
I have used "require q(some/file)" in the "Magic JuJu" location, but that does not maintain the persistent variable scope, i.e. subs from the external file don't "see" the object attribute hashes correctly (in still other words, putting the require at the top of the file would have the same effect). I could get around that by always using setters and getters. So that is not a deal breaker, but would require a bit of coding time and execution overhead that I'd rather not incur.
Finally, I don't want to extend the class; it already has multiple inheritance. I just want a simple "insert code here" approach would bring the code in once at compile time.
In summary:
- (Required) imports code from external files into package namespace
- (Required) Does so only at compile-time or minimal run-time overhead
- (Required) Does not extend class
- (Desired) Honors insert location scope
Example Code with "Magic JuJu" comment below:
package T;
use strict;
use warnings;
########## BEGIN object persistent variables scope block ############
{
my %Attr_Name_Env;
## Constructor 'new'
#
sub new {
## Get and confirm arguments
#
my $class = shift;
my $href_arg = {开发者_如何学运维@_};
my $name_env = $href_arg->{'name_env'};
## Bless anon scalar into class
#
my $obj_new = bless anon_scalar(), $class;
my $idx_self = ident $obj_new;
# Populate object attributes
#
$Attr_Name_Env{ $idx_self } = $name_env;
return $obj_new;
}
## END Constructor 'new'
sub DESTROY {... as you do ...}
sub t_get_name_env {
my $self = shift;
my $idx_self = ident $self;
return $Attr_Name_Env{ $idx_self };
}
## insert magic juju here
}
########## END object persistent variables scope block ############
1;
Maybe a BEGIN block with a slurp and eval ...
You could just use the modules and import the desired subs.
use MyMod qw( wanted_sub_1 wanted_sub2 );
To get access to your attribute hashes you will need to modify import
for your target modules.
package MyClass;
use MyMod { attrib1 => \%attrib1, attrib2 => \%attrib2 }, qw( wanted_sub1 wanted_sub2 );
MyMod
's import
would then create code refs that are closed over the initial hash argument, and install those into the MyClass
namespace.
If you are willing to live with the consequences, there is Filter::Macro.
精彩评论