Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Re: using a variable to specify which perl module to use

by broquaint (Abbot)
on Jul 15, 2003 at 17:32 UTC ( [id://274492]=note: print w/replies, xml ) Need Help??


in reply to using a variable to specify which perl module to use

Just mimic use like so
BEGIN { $module = somecond() ? "Text::CSV" : "Text::CSV_XS"; require $module; $module->import; }
The if module may also be another option.
HTH

_________
broquaint

Replies are listed 'Best First'.
Re^2: using a variable to specify which perl module to use (bareword)
by tye (Sage) on Jul 15, 2003 at 18:15 UTC

    require "Text::CSV" is much different than require Text::CSV. For your code to work, you'd need to s-::-/-g on $module for the require (but not for the import).

    You can also use a lexical. Note that my declarations happen when the statement is compiled but my initializations happen when the statement is run. So:

    use strict; my $module; BEGIN { $module= ... ? 'Text::CSV' : 'Text::CSV_XS'; my $file= $module; $file =~ s-::-/-g; require "$file.pm"; $module->import(); } my $csv = $module->new();
    Using eval "use $module" avoids this complication. Which to prefer is mostly a matter of taste (unless there is "risk" of $module ending up containing something strange).

                    - tye

      Actually, no, it's not a matter of taste. It's best to avoid eval STRING whenever possible since it forces dynamic runtime recompilation, and is thus rather slow. An eval BLOCK is always preferable. If you can represent the package names as literals (barewords) within your program, use this:

      if (something()) { eval { require Text::CSV; Text::CSV->import; } } else { eval { require Text::CSV_XS; Text::CSV_XS->import; } }

      The eval BLOCK syntax as well allows you to catch any fatal errors, storing them in $@:

      die "Couldn't load module: $@" if ($@);
        It's best to avoid eval STRING whenever possible since it forces runtime recompilation, and is thus rather slow.

        Avoiding string eval is generally good advice. Always avoiding it just for speed reasons is premature micro optimization. If you were doing this in a loop and profiling showed that it was actually causing you a noticeable slow-down, then that would be a good reason to refactor the code to avoid it.

        My taste leads me to prefer much simpler code that runs a few milliseconds slower nearly every time.

        You left out the code to set what class to use when creating the object(s). If you add that in, then you are having to say each package name 3 times. I'd rather use the code I provided above. (:

        Thanks for mentioning the fatal error trapping. In this situation, eval's trapping of errors is a disadvantage. I should have mentioned that the extra step would be required if the "simpler" eval "use $module" were used. I'd just die "$@\n" if $@; so that the error message is as expected.

        Also note that you need to put the die code inside the BEGIN block in your code above.

                        - tye
      require "Text::CSV" is much different than require Text::CSV
      Ah yes, of course. I've written code to do the appropriate munging of a bareword many times, don't know why I forgot it this time. Anyhow my code should really look like this
      BEGIN { (my $file = ($module = somecond() ? "Text::CSV" : "Text::CSV_XS")".pm") =~ s{::}(/)g; require $file; $module->import; }

      HTH

      _________
      broquaint

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://274492]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (4)
As of 2024-04-19 04:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found