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

Hi, I want to import some perl modules inside a program.
I have many perl modules (say module_john.pm, module_kevin.pm, module_mary.pm)
in all the following directories: ./dir_sunday, ./dir_monday, ./dir_friday etc..
While running the program I am not able to specify which perl module (in which dir) I want to choose.
How can I use variables in "use" and "@INC" statements ?
My Program is given below.
========================== 1 #!/usr/bin/perl 2 3 $day = "sunday"; # This input is expected from the user while +running. 4 $userId= "mary"; # This input is expected from the user while +running. 5 6 BEGIN { 7 push (@INC, "./dir_$day"); 8 } 9 10 $tmp = "module_".$userId; 11 12 use $tmp qw(%diary); # %diary is a hash in the perl module + ./dir_sunday/module_mary.pm 13 *diary = \ %diary::diary; 14 15 <Program body> ===================================
I am getting errors
"cant locate file module_mary.pm in @INC" and "Syntax error if I use $tmp in line No:12"

Replies are listed 'Best First'.
Re: How to use variables in @INC and "use" commands
by Corion (Patriarch) on Oct 21, 2008 at 14:18 UTC

    use doesn't work that way. use always wants a bareword and not a variable as the module name. To dynamically load a module, use require:

    ... my $module_file = "$tmp.pm"; require $module_file; $module_file->import(qw(%diary));

    Then you can even ditch the @INC hackery:

    ... my $module_file = "dir_$day/$userId.pm"; require $module_file; $module_file->import(qw(%diary));
Re: How to use variables in @INC and "use" commands
by holli (Abbot) on Oct 21, 2008 at 14:32 UTC
    Though I personally believe that your setup is flawed, the following may work:
    use Module::Load; $day = "sunday"; $userId = "mary"; load("$day::module_$userId", qw(%diary)); *diary = \ %diary::diary;


    holli, /regexed monk/
Re: How to use variables in @INC and "use" commands
by ikegami (Patriarch) on Oct 21, 2008 at 18:04 UTC

    You have a second problem.

    $day = "sunday"; $userId= "mary"; BEGIN { push (@INC, "./dir_$day"); } ...

    is processed as follows:

    • $day = "sunday"; is compiled.
    • $userId= "mary"; is compiled.
    • BEGIN { push (@INC, "./dir_$day"); } is compiled.
    • BEGIN { push (@INC, "./dir_$day"); } is executed.
    • ... is compiled.
    • $day = "sunday"; is executed
    • $userId= "mary"; is executed
    • ... is executed

    As you can see, $day is only given a value long after the BEGIN block uses them. It always amazes me that people are willing to come to PerlMonks to find a problem with their code when use warnings; would have told them. The two most useful tools:

    use strict; use warnings;

    Solution:

    my $userId= "mary"; BEGIN { my $day = "sunday"; push (@INC, "./dir_$day"); } ...

    All together:

    #!/usr/bin/perl use strict; use warnings; BEGIN { my $day = "sunday"; my $userId = "mary"; push (@INC, "./dir_$day"); eval "use module_$userId qw( ); 1" or die $@; *diary = \%diary::diary; }

    It doesn't make much sense to specify %diary on the use line do the alias via an assignment. That means the %diary on the use line is being ignored. You can fix that by using Exporter. Then you'd replace the last two lines with:

    eval "use module_$userId qw( %diary ); 1" or die $@;

    By the way, please don't include line numbers in posted code. We are quite able to count to fifteen. All it does is make it very hard to cut and paste.

Re: How to use variables in @INC and "use" commands
by pjotrik (Friar) on Oct 21, 2008 at 15:52 UTC
    or 'eval' the use:
    eval('use dir_'.$day.'::'.$userId.' qw(\%diary)'); print "Can't use dir_$day::$userId module: $@";
    If you choose to use require, beware that if you give it a string, it expects it to be a file name/path, not the module name.
Re: How to use variables in @INC and "use" commands
by dragonchild (Archbishop) on Oct 21, 2008 at 16:33 UTC
    It sounds like your storing data in a Perl module. Much better would be to use DBM::Deep, DB_File, or any number of other data storage mechanisms.

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
      Thanks a lot for your view.
      I will look in to it.
      :-)
Re: How to use variables in @INC and "use" commands
by cdarke (Prior) on Oct 21, 2008 at 16:47 UTC
    You may wish to take a different angle. Insert a higher level class between main and your module_name classes. In the new class dynamically bless the object to be the correct class at runtime. What was that? You are not using OO? Actually you don't need to, just use the blessed reference to make the calls on.
    Update: Although you will still have to load all the modules :-(