I had the same issue as well. I wrote a class (attached) to encapsulate references to routines via the name so that I could lazy-load them (this is useful for template systems to avoid loading every possible tag implementation every time). The logic tries to load the package for the symbol if not present and assumes that all names are qualified (in the real code, that is verified at a higher level). After the first invocation, the code pointer is cached and used on subsequent invocations.

# -----------------------------------------------------------------------------
package Transfinitum::WikiVar::CodeRef;
# This is a specialized class just for handling references to subroutines.
# Bad things happen with AUTOLOAD if we try to capture a CODE reference before
# the symbol is defined. As a result, we need to pass in an object that has
# the name and can cache a CODE pointer so that we can lazy eval the CODE
# reference and potentially pull in the supporting package to avoid AUTOLOAD
# entirely.

# Two members, the fully qualified name and the CODE reference
use constant NAME_IDX => 0;
use constant CODE_IDX => 1;

# First argument is fully qualified name.
# Optional second is a CODE pointer. This is useful for closures
sub new {
    bless [ $_[1], $_[2]], $_[0];
}

sub getName { return $_[0]->[NAME_IDX]; }

# Get a CODE pointer from the CodeRef.
# Returns a CODE object if it found the subroutine, or a string with
# an error condition if not.
sub getCode {
    my ($self) = @_;
    my $status;
    
    if (not $self->[CODE_IDX]) { # no cached pointer
        no strict 'refs';
        # see if it's there already
        my $name = $self->[NAME_IDX];
        $self->[CODE_IDX] = *{$name}{CODE};
        if (not $self->[CODE_IDX]) {
            # not there, try to bring in the package
            $self->[NAME_IDX] =~ m!(.*)::(?:[^:]+)$!o;
            my $p = $1; # package name
            eval "require $p;";
            if ($@) {
                $status = 'Defun Error: Failed to load package "' . $p
                        . '" for subroutine "' . $name
                        . '" because "' . $@ . '"';
            } else {
                $self->[CODE_IDX] = *{$name}{CODE};
                if (not $self->[CODE_IDX]) {
                    $status = 'Defun Error: Undefined subroutine "'.$name.'"';
                }
            }
        }
    }
    return $status ? $status : $self->[CODE_IDX];
}
_______________________________________________
ActivePerl mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Reply via email to