In "Perl Best Practices" the very first line in the section on AUTOLOAD is:
Don't use AUTOLOAD
However all the cases he describes are dealing with OO or Modules.
I have a stand alone script in which some command line switches control which versions of particular functions get defined. Now I know I could just take the conditionals and the evals and stick them naked at the top of my file before everything else, but I find it convenient and cleaner to put them in AUTOLOAD at the end of the file.
Is this bad practice / style? If you think so why, and is there a another way to do it?
As per brian's request
I'm basically using this to do conditional compilation based on command line switches.
I don't mind some constructive criticism.
sub AUTOLOAD {
our $AUTOLOAD;
(my $method = $AUTOLOAD) =~ s/.*:://s; # remove package name
if ($method eq 'tcpdump' && $tcpdump) {
eval q(
sub tcpdump {
my $msg = shift;
warn gf_time()." Thread ".threads->tid().": $msg\n";
}
);
} elsif ($method eq 'loginfo' && $debug) {
eval q(
sub loginfo {
my $msg = shift;
$msg =~ s/$CRLF/\n/g;
print gf_time()." Thread ".threads->tid().": $msg\n";
}
);
} elsif ($method eq 'build_get') {
if ($pipelining) {
eval q(
sub build_get {
my $url = shift;
my $base = shift;
$url = "http://".$url unless $url =~ /^http/;
return "GET $url HTTP/1.1${CRLF}Host: $base$CRLF$CRLF";
}
);
} else {
eval q(
sub build_get {
my $url = shift;
my $base = shift;
$url = "http://".$url unless $url =~ /^http/;
return "GET $url HTTP/1.1${CRLF}Host: $base${CRLF}Connection: close$CRLF$CRLF";
}
);
}
} elsif ($method eq 'grow') {
eval q{ require Convert::Scalar qw(grow); };
if ($@) {
eval q( sub grow {} );
}
goto &$method;
} else {
eval "sub $method {}";
return;
}
die $@ if $@;
goto &$method;
}
The AutoSplit and AutoLoader modules automate the creation of forward declarations. The AutoSplit module creates an 'index' file containing forward declarations of all the AutoSplit subroutines. When the AutoLoader module is 'use'd it loads these declarations into its callers package.
Starting with AutoLoader 5.73, you can call the AutoLoader::autoload_sub function with the fully-qualified name of the function to load from its .al file. The behaviour is exactly the same as if you called the function, triggering the regular AUTOLOAD mechanism, but it does not actually execute the autoloaded function.
SelfLoader - an autoloader that doesn't use external files. AutoLoader is maintained by the perl5-porters. Please direct any questions to the canonical mailing list. Anything that is applicable to the CPAN release can be sent to its maintainer, though. Author and Maintainer: The Perl5-Porters <[email protected]>
AutoLoader may fail to find the autosplit files (or even find the wrong ones) in cases where @INC contains relative paths, and the program does chdir. SelfLoader - an autoloader that doesn't use external files.
If your only reason for using AUTOLOAD
is to relocate the block to the end, why not put it at the end in a subroutine, and then call it as soon as its dependent variables are defined?
sub tcpdump; # declare your subs if you want to call without parens
# define the parameters
compile();
# code that uses new subs
sub compile {
*tcpdump = $tcpdump ? sub {
my $msg = shift;
warn gf_time()." Thread ".threads->tid().": $msg\n";
} : sub {};
# ...
}
# EOF
Better still, if the globals aren't needed elsewhere, just pass the values to compile
as arguments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With