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

I have a need to do something like the following:
package foo; use strict; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( $a, $b ); our $a = 1; our $b = 2; 1; package bar; use strict; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( $a, $b ); our $a = 99; our $b = 7775; 1; #!/usr/bin/perl use strict; use warnings; use foo; &a sub a { do something to $a; do something to $b }
now - Id like to have several packages all using $a and $b so what Id like to do is something like
#!/usr/bin/perl use strict; use warnings; use $ARGV[0]; blah blah blah
and call it like  script.pl foo

As im writing this it sounds a bit hokey, but im still curious if this or some variant is possible...

UPDATE
BTW I cant do perl -Mfoo script.pl because foo is not in a path in @INC.

Ted
--
"That which we persist in doing becomes easier, not that the task itself has become easier, but that our ability to perform it has improved."
  --Ralph Waldo Emerson

Replies are listed 'Best First'.
Re: modules as variables
by davido (Cardinal) on Jun 28, 2006 at 18:24 UTC

    Ok, you can't specify which module to load via @ARGV with use. use basically works its magic at compile time, and has already done its thing before $ARGV[0] is ever determined.

    You might be able to do it with require. The documentation for use states the following:

    It (use) is exactly equivalent to

    BEGIN { require Module; import Module LIST; }

    Please consider using variables other than $a and $b. Those variables have special meaning inside sort routines, and you'll create potential for all sorts of havoc if you steal them for your own use.

    You know, Perl actually already offers you a better solution anyway. If your need is to supply the module name on the command line, don't rely on @ARGV. Instead, use Perl's command line switch, "-M", like this:

    perl -MFoo myscript.pl

    See perlrun for details.

    An update:
    You can probably still use -M even if your module resides along a path not specified in @INC. You can deal with this difficulty using either the -I[directory] switch, or the -f switch, which are also documented in perlrun.


    Dave

      Ok, you can't specify which module to load via @ARGV with use. use basically works its magic at compile time, and has already done its thing before $ARGV[0] is ever determined.

      No, not at all. @ARGV is available at compile time, and Perl is capable of executing expressions such as $ARGV[0] at compile time. The problem is that use expects a bareword for argument, not an expression. The generic workarounds (eval "use $ARGV[0]" and converting from namespace to filename for require) have already been posted.

      Thanks.
      $a and $b are just used for the snippet - they arent the vars used.
      Ted
      --
      "That which we persist in doing becomes easier, not that the task itself has become easier, but that our ability to perform it has improved."
        --Ralph Waldo Emerson

        Neither should they be used in snippets, as they lead to panic in the responses you get. ;)


        Dave

Re: modules as variables
by Solo (Deacon) on Jun 28, 2006 at 18:35 UTC
    With the caveat that what you're doing looks like it should be handled as configuration data, here's some code that roughly accomplishes what you want.

    use warnings; use strict; BEGIN { (my $filename = $ARGV[0]) =~ s!::!/!g; require "$filename.pm"; $ARGV[0]->import() if $ARGV[0]->can('import'); } print read_file($0);

    In this case, the intent is to run perl code.pl File::Slurp.

    --Solo

    --
    You said you wanted to be around when I made a mistake; well, this could be it, sweetheart.
      Yes - its configuration data - but im porting someone else's code over to a new system that I NEED to get up and running as quickly as possible, next step is to actually fix the code.

      Thanks
      Ted
      --
      "That which we persist in doing becomes easier, not that the task itself has become easier, but that our ability to perform it has improved."
        --Ralph Waldo Emerson
Re: modules as variables
by ikegami (Patriarch) on Jun 28, 2006 at 18:58 UTC

    Completely differently, you could use do to insert the code into the current namespace.

    foo.pl:

    our $var_a = 1; our $var_b = 2; 1;

    bar.pl:

    our $var_a = 3; our $var_b = 4; 1;

    main.pl:

    #!/usr/bin/perl use strict; use warnings; do $ARGV[0].'.pl' or die; our $var_a; our $var_b; print("$var_a, $var_b\n");

    Output:

    >perl 558119.pl foo 1, 2 >perl 558119.pl bar 3, 4
Re: modules as variables
by shmem (Chancellor) on Jun 28, 2006 at 18:31 UTC
    To 'use' a module provided as argument on the commandline, you have to wrap it into a string eval:
    #!/usr/bin/perl use strict; use warnings; BEGIN { eval "use $ARGV[0]"; die $@ if $@; shift; # take first arg out of @ARGV }
    because saying use $var with $var holding a package name is not possible.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: modules as variables
by davidrw (Prior) on Jun 28, 2006 at 18:26 UTC
    note related to primary question, but don't use $a and $b as variable names, since they're special globals used by sort

    As for use $ARGV[0];, see require and eval