Based on your comments, and wanting to explore/
ABUSE an idea, I came up with the following:
#!/usr/bin/perl
use strict;
local $\ = '-' x 40 . "\n";
eval { my $test = CGI::thisFunctionDoesNotExist() };
print $@;
eval { my $test = thisFunctionDoesNotExist CGI() };
print $@;
eval { my $test3 = new Some::Package::That::Doesnt::Exist() };
print $@;
# A function that does not exist in main::
functionThatDoesntExist('test');
exit;
sub UNIVERSAL::AUTOLOAD {
my $method = $UNIVERSAL::AUTOLOAD;
# So that we have the Carp methods without
# cluttering up our UNIVERSAL namespace
use Carp ();
# First, if they are in the main namespace,
# Fail, since we don't have a package to load
if ($method =~ /^main::/) {
Carp::croak("AUTOLOAD failed: $method");
}
# Else, split the name into package and method names
my @methodParts = split('::', $method);
my $methodName = pop(@methodParts);
my $package = join('::', @methodParts);
# Now, load the package.
# Die if it fails
eval "use $package";
Carp::confess($@) if ($@);
# If you made it here, do standard autoload stuff
# Check which form of method call this is
# This will catch the packageName::methodName format
# The methodName packageName format is already good
if ($_[0] ne $package) {
unshift @_, $package;
};
no strict;
# the goto call will pass along @_ transparently
goto &$method;
};
This is an example run:
~johannz >./autoload.pl
Undefined subroutine CGI::thisFunctionDoesNotExist
----------------------------------------
Undefined subroutine CGI::thisFunctionDoesNotExist
----------------------------------------
Can't locate Some/Package/That/Doesnt/Exist.pm in @INC (@INC contains: /usr/bin/perl/lib/ .) at (eval 3) line 2.
BEGIN failed--compilation aborted at (eval 3) line 2.
UNIVERSAL::AUTOLOAD('Some::Package::That::Doesnt::Exist') called at ./autoload.pl line 11
eval {...} called at ./autoload.pl line 11
----------------------------------------
AUTOLOAD failed: main::functionThatDoesntExist at ./autoload.pl line 27
UNIVERSAL::AUTOLOAD('test') called at ./autoload.pl line 15
I would never allow this code past a code review, but it does allow you to make method calls dynamically. Never again will you need to use the EVIL 'use' statement. Down with Clarity, Up with Obfuscation!!!
Note: This whole thing is an example of how perl gives you enough rope to hang yourself. I wanted to explore the possibilities of the what the UNIVERSAL class and AUTOLOAD methods make possible. Indigo was part of the inspiration for this during a talk over the cube walls
|