BerntB has asked for the wisdom of the Perl Monks concerning the following question:

I have some persistent objects dumped into a database. To make certain that the object's package is loaded when reading in the object, I use this:
return if $class->can('new'); eval "use $class"; croak("Err etc") if $@;
This works but I wonder about efficiency. Two questions: It would also be nice with a more general method than demanding the existence of a method!

I found an alternative to can a while ago by searching the usual suspects (Google, my books, monks). To see if the package is loaded, check for a package's symbol table:

return if defined %{$class . "::"};

This symbol table test didn't work consistently for me? Should it -- did I do something wrong?

Yes, I am optimizing the wrong details. I haven't kludged around with the symbol tables much and is fishing a bit for discussion and pointers. :)

Maybe I should just get some more books, but I am looking for work right now. :-)

Replies are listed 'Best First'.
Re: Most effective way to dynamically load a module?
by tilly (Archbishop) on Aug 22, 2006 at 04:06 UTC
    Simpler answer. Change your eval to eval "use $class ()"; and drop the can.

    Check the documentation, use already checks whether a class is loaded and doesn't reload it the second time. That check is more efficient than calling can. However use will call import. Since you don't need the calls to import, the empty parens can be used to get rid of them.

      Yes, but isn't eval expensive? It has to start up the Perl parser, etc.
        Define expensive.

        eval isn't free, but it doesn't cost that much. In any case this is all micro-optimization that is unlikely to matter much.

        If you have to do it at runtime, just use require. It won't call import, and it won't load a module if it's already loaded.
Re: Most effective way to dynamically load a module?
by jbrugger (Parson) on Aug 22, 2006 at 05:04 UTC
    Eval works ok, but you're using the 'quote' version here, so i'd do a
    if ($class !~ /^[a-z0-9_]*$/i) { print $cgi->header(); print "<h1> You tried something that's not allowed! </h1><br>< +br>"; exit(); }
    before using the eval statement.
    Alternative you'd be able to use:
    eval { require $class . ".pm"; }; if ($@) { print $cgi->header(); print "$@"; print "<h1> The class '$class' does not exist! </h1><b +r><br>"; } else { # Do your stuff. $class->main($cgi,$user); }
    "We all agree on the necessity of compromise. We just can't agree on when it's necessary to compromise." - Larry Wall.