Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

use module if condition is met

by Grygonos (Chaplain)
on Jan 23, 2004 at 17:01 UTC ( #323606=perlquestion: print w/replies, xml ) Need Help??
Grygonos has asked for the wisdom of the Perl Monks concerning the following question:

Felllow Monks,

Here is the basic idea of what I'm attempting, I want to use a different module depending on what client my script runs for. Secondly,there are some functions that exist in one client module that may not exist in another. I would like to check for the existance of a sub before I call it.

if($type eq 'x') { use Some::Module; } #*pseudo* if(subExists('mysubtocheck')) { mysubtocheck(); }

Is this possible, or a good idea? Can you suggest some alternatives?

Thanks again monks,


Replies are listed 'Best First'.
Re: use module if condition is met
by broquaint (Abbot) on Jan 23, 2004 at 17:08 UTC
    For conditional a use statement, see the if module. But if you're happy to include your modules at runtime then a simple require will be be. Finally, to check for the existence of a subroutine you can simply use defined e.g
    defined &mysubtocheck && mysubtocheck();
    Although make sure you use parens when calling a dynamically defined subroutine otherwise you'll get a compile-time error under strict 'subs'.


Re: use module if condition is met
by Abigail-II (Bishop) on Jan 23, 2004 at 17:16 UTC
    use if $type eq 'x', Some::Module;

    Of course, that requires the value of $type to be known at compile time. Otherwise, do something like:

    if ($type eq 'x') { require Some::Module; Some::Module -> import if Some::Module -> can ("import"); }


Re: use module if condition is met
by ysth (Canon) on Jan 23, 2004 at 17:34 UTC
    If $type is known when your script is compiling (e.g. based on operating system or information in @ARGV), use the if module for this:
    use if $type eq 'x', "Some::Module";
    (Your try at if ($type eq 'x') { use Some::Module } doesn't work because the use will be performed at compilation time, before the check of $type even happens.)

    Otherwise, use some form like eval "use $module" or eval { require $module; $module->import; } (but not eval { use $module }, because there the use is again performed at compilation time).

    Having the use happen at run-time is not ideal, because there can be differences in how your code will compile; e.g.:

    $perl -we'eval "use Errno qw/EINVAL/"; print EINVAL' Name "main::EINVAL" used only once: possible typo at -e line 1. print() on unopened filehandle EINVAL at -e line 1. $perl -we'use Errno qw/EINVAL/; print EINVAL' 22
    To detect if a subroutine exists, use exists(&subname). This will not detect subs that would be AUTOLOADed, unless they have a forward declaration (e.g. sub Foo;). defined(&subname) is slightly different and probably not what you want; see perldoc defined and exists.
      Thanks monks, the if module worked perfectly. I simply passed my client name as $ARGV[0] and it works.

Re: use module if condition is met
by tcf22 (Priest) on Jan 23, 2004 at 17:06 UTC
    Perhaps something like this:
    if($type eq 'x'){ eval "use Some::Module"; } eval { mysubtocheck(); }; if($@){ #Sub ran }else{ #Sub not present or died }

    - Tom

Re: use module if condition is met
by cfreak (Chaplain) on Jan 23, 2004 at 17:12 UTC

    use requires code in at compile time so what you have really won't work. Your could use require which will do it at run-time but is slower. The best approach I've seen (believe this is in the Camel Book) is to use a BEGIN block in combination with eval. However that is going to only test if the module is installed, I don't believe variables such as your $type would be initialized yet (I could be wrong on that one)

    Then of course you have the problem with your subs. You could create an AUTOLOAD in your modules that would capture any calls to subs that didn't exist and return some kind of flag to that affect.

    Honestly though I think all that is really more work that you want. I think requireing the modules is going to be slower than just useing all the ones you may need even if you don't make calls to all of them. Then you don't have to worry about undefined subs either.

    Lobster Aliens Are attacking the world!
      Not that it really matters, but require is not slower than use. If anything, it would be faster, since it does less.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://323606]
Approved by cfreak
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (6)
As of 2017-01-21 22:27 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (186 votes). Check out past polls.