On 8/7/07, Fermín Galán Márquez <[EMAIL PROTECTED]> wrote:
> Hi!
>
> I'm trying to introduce conditional module loading in a Perl program,
> but I'm experiencing problems. For example:
>
> ...
> if ($some_condition) {
>     use ModuleA;
>     (doing something using ModuleA)
> }
> else {
>     use ModuleB;
>     (doing something using ModuleB)
> }
>
> That is, if $some_condition is true then load the ModuleA, if false load
> ModuleB. However, it doesn't seem to work this way and I've observed
> (counterintuitively :) that both modules are always loaded (ModuleA and
> ModuleB), no matter the value of $some_condition.
>
> Is it possible to do such "conditional module loading" in Perl? What am
> I doing wrong? Some workaround?
snip

This is because a use statement is syntactic sugar for a BEGIN block
and all BEGIN blocks run before your program starts (there are five
phases BEGIN, INIT, CHECK, your code, and END).

There are two ways to conditionally load a module: write the BEGIN
block, require, and import statements yourself or use the string form
of eval*.  However, this is rarely a good idea.  Most of the time
people want to do this so they can use different versions of the same
module (a test vs a prod version).  This is better handled though the
use of the PERL5LIB environmental variable to override which module is
found than through runtime hacks.  There are only two other reasons I
can think of to conditionally load a module: factory classes and
namespace pollution issues.  If you want to create a factory class
then I would take a good look at how the DBI module is handling things
and emulate it (in particular the connect and install_driver methods).
 If you are having namespace pollution issues it is better to fix the
modules in question than to add runtime hacks to your code.

There is one last case, but it doesn't involve loading A or B, it
involves loading A if it is available and setting a flag as to whether
it is available or not.  For example, I once wrote a Gtk based SQL
Editor/Runner.  It had the ability to save the result sets to
Microsoft Excel files, but not everyone on the team had
Spreadsheet::WriteExcel installed, so I had to add a hack** like this
to the code

our $can_write_xls = eval "use Spreadsheet::WriteExcel; 1";

Then later in the code

sub save_file_xls {
    my ($name, $rs) = @_;

    unless ($can_write_xls) {
            error("Spreadsheet::WriteExcel is not installed, please
choose another format");
            return;
    }

    #save the result set
}

* this is one of the few valid uses of string eval, but only when the
string is hard coded.
** a more elegant solution would have been to prevent the user from
being able to choose xls as a format, but the type was inferred from
the extension and I was too lazy to change that.

--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/


Reply via email to