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

Hi. I am trying to modify some code to search human genome space to use it for multiple species. I have it set so that if the following code worked, it would be a very simple process...
if ($species eq "H") {use human;} elsif ($species eq "M") {use mouse;}
the two perl modules are the same except for chromosome numbers and lengths (same subroutine names). Right now, it seems like perl is ignoring the conditional. Is there any way I can get around this easily? Thanks!

Replies are listed 'Best First'.
Re: use module question.
by jeffa (Bishop) on Aug 04, 2005 at 15:33 UTC

    use statements are always loaded first, regarless of what run time conditions you throw on them. For example:

    if (0) { use Data::Dumper; } print Dumper [1..10];
    Try using require instead. But i would actually use an Object Oriented approach and instantiate the appropriate object instead. In fact, this is good case for using Class::Factory

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      Thanks everyone! require did the trick.
Re: use module question.
by kwaping (Priest) on Aug 04, 2005 at 15:34 UTC
Re: use module question.
by gellyfish (Monsignor) on Aug 04, 2005 at 15:38 UTC

    You probably want something like:

    if ($species eq "H") { require human; human->import(); } elsif ($species eq "M") { use mouse; mouse->import(); }
    The reason that what you had didn't work is that the use happens are compile time before the code is executed.

    You might want to consider using proper cased names for your modules as all lowercase names are conventionally reserved for pragmatic modules such as strict

    /J\

Re: use module question.
by Zaxo (Archbishop) on Aug 04, 2005 at 15:41 UTC

    The if.pm module is useful for that,

    use if $species eq 'H', 'human'; use if $species eq 'M', 'mouse';
    Make sure that $species is set at compile time (that's probably why it's being ignored).

    This looks like a natural place for inheritance, though. Let Human.pm and Mouse.pm inherit from Mammal.pm, which carries the common subroutines.

    After Compline,
    Zaxo

Re: use module question.
by friedo (Prior) on Aug 04, 2005 at 16:00 UTC
    The Monks above are all correct that using require or use if will allow you to load the module at runtime based on your conditional. But I think this is a perfect place for taking advantage of one of the most powerful OO features, polymorphism.

    use Human; use Mouse; my %classes = ( H => 'Human', M => 'Mouse' ); my $species = get_species(); # returns 'H' or 'M' my $organism = $classes{$species}->new;

    This will allow you to instantiate a different object depending on whatever is returned by the get_species function. For more, take a look at perltoot.
Re: use module question.
by blazar (Canon) on Aug 04, 2005 at 15:35 UTC
    No, no, no! It may be confusing, but indeed use is executed at BEGIN time. Check perldoc -f require.
Re: use module question.
by jeteve (Pilgrim) on Aug 04, 2005 at 15:45 UTC
    Hi ! Most dynamic way to do it:
    my $spec = .... ; # H, M , etc... my $mod = "mod".$spec ; # Modules named modH , modM , etc.. eval "require $mod;"; if( $@ ){ die "Cannot load module $mod for specie $spec : $@"; } #Then, use your module function f1 , f2.. by: $mod->f1() or $mod::f2() etc...
    This way, anytime you have a new specie to handle you just have to write a new module, without modifying your using code.

    In general, avoid to construct case like structure. It makes your code hard to maintain and is a bit outdated.

    Dynamicity of perl is easy to write and very rewarding to use. Use it !! J.

    Nice photos of naked perl sources here !