Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

using a variable to specify which perl module to use

by princepawn (Parson)
on Jul 15, 2003 at 17:29 UTC ( [id://274487]=perlquestion: print w/replies, xml ) Need Help??

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

I managed to use a variable to specify which of two modules with the same API I wanted to use (one uses XS, the other does not). But I am not sure my solution is cleanest. Does anyone have a suggestion for a cleaner way to do this?
BEGIN { + $main::MODULE = 'Text::CSV'; # $main::MODULE = 'Text::CSV_XS'; my $string = "use $main::MODULE;"; eval $string; } my $csv = $main::MODULE->new;

Carter's compass: I know I'm on the right track when by deleting something, I'm adding functionality

Replies are listed 'Best First'.
Re: using a variable to specify which perl module to use
by broquaint (Abbot) on Jul 15, 2003 at 17:32 UTC
    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

      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 ($@);
        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

Re: using a variable to specify which perl module to use
by Ovid (Cardinal) on Jul 15, 2003 at 18:37 UTC

    Why use Text::CSV? It's slower and it's broken. If you have Text::CSV_XS, use it. It's faster and it's not broken. In any event, here's one way (untested):

    my $CSV_CLASS = $boolean ? $module1 : $module2; eval "use $CSV_CLASS"; if ($@) { croak "Could not use $CSV_CLASS: $@"; } my $csv = $CSV_CLASS->new;

    Cheers,
    Ovid

    Looking for work. Here's my resume. Will work for food (plus salary).
    New address of my CGI Course.

Re: using a variable to specify which perl module to use
by flounder99 (Friar) on Jul 15, 2003 at 18:35 UTC
    This sounds like a good application of a subclass;
    create a MyText.pm:
    package MyText; sub init_XS { my $class = shift; my $usexs = shift; if ($usexs) { eval { use Text::CSV_XS; @ISA = ('Text::CSV_XS'); } } else { eval { use Text::CSV; @ISA = ('Text::CSV'); } } } 1;
    Then in your program do this:
    use MyText; my $usexs = 1; #decide whether to use XS MyText->init_XS($usexs); my $csvobj = MyText->new(); #Text::CSV_XS->new gets called if $usexs is true. #Text::CSV->new gets called if $usexs is false. #do stuff with $csvobj

    --

    flounder

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://274487]
Approved by allolex
Front-paged by tye
help
Chatterbox?
and the web crawler heard nothing...

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

    No recent polls found