Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

require $variable; import $variable (@array) fails

Status
Not open for further replies.

gnubie

Programmer
Joined
Apr 16, 2002
Messages
103
Location
US
I want the perl script to conditionally select between two modules.

Hard coding the module name and using use works, so I know the module interface is correct. Hard coding the required module name works. The problem is when I use a variable for the module name. It should work. I've seen examples, but it does not. Help.

# This works
require Reminderst;
import Reminderst qw(@annualReminders);
print "Annual Reminders 0: $annualReminders[0]{subject}\n";
exit;

# This gets "Can't locate Reminderst in @INC (@INC contains: C:/Perl/lib C:/Perl/site/lib .) at d:\perlscripts\reminder\reqtest.pl line 11."
$moduleName = "Reminderst";
require $moduleName;
import $moduleName qw(@annualReminders);
print "Annual Reminders 0: $annualReminders[0]{subject}\n";
exit;

# This gets no compile errors, but doesn't import arrays
$moduleName = "Reminderst.pm";
require $moduleName;
import $moduleName qw(@annualReminders);
print "Annual Reminders 0: $annualReminders[0]{subject}\n";
exit;

#
# Here is module for above (in current directory).
#
package Reminderst;
use Exporter();
@ISA=('Exporter');
# Explicitly export the following
@EXPORT=('@annualReminders');

@annualReminders=(
{
datestamp=>'080126',
recipient=>"Geo",
subject=>'Annual Reminder Test',
message=>'Annual Reminder Test.',
}
);
1





 
I believe if you read the "require" function documentation you will figure out why your code is doing what it is. Give it a read and if you still have questions afterwards post again:




------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
The error message says that it simply cannot find the path to your module in @INC. Print @INC
Code:
perl -e 'print map {"$_\n"} @INC;'
and check whether your module is in one of the directories listed.

One explanation for your symptom is that the current directory (.) is in @INC and you are testing the two different scripts from different directories.

You can add directories to @INC at run-time, most naturally with code like
Code:
use lib '/path/to/my/libs';

["]As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs.["]
--Maur
 
Thanks for your help. I read about require until my eyes bled. I couldn't get it to work. However, in my research I found the perfect solution for conditional use on perlmonks.org.

use if ($^O eq 'MSWin32'), 'Win32::OLE';

or in my case, this works:

# $opt_t from the command line
use if ($opt_t), 'Reminderst';
use if (!$opt_t),'Reminders';
print "Annual Reminders: $AnnualReminders[0]{subject}\n";
exit;
1


 
that would fail if your original script failed, so you may have accidentally solved the original problem. It's worth trying to understand why the original code failed or you may well hit the same problem later.

The syntax you have chosen is quite unusual and, I think, would confuse most perl programmers. In particular, the commas after the bracketed conditions are very strange.

A more natural idiom would be
Code:
use 'Reminderst' if $opt_t;
use 'Reminders' unless $opt_t;
or, making the logic even more apparent,
Code:
use $opt_t ? 'Reminderst' : 'Reminders';
Yours,

["]As soon as we started programming, we found to our surprise that it wasn't as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs.["]
--Maur
 
I have to agree, since only one condition must be true even a simple if/else block would be better:

Code:
if ($var) {
   use Foo;
}
else {
   use Bar;
}


I don't think this works:

Code:
use $opt_t ? 'Reminderst' : 'Reminders';

the module must be a bareword.









------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Fishiface: you are probably right. I used it as copied.
KevinADC: NO. Actually, this is the problem I'm trying to overcome, because:

1. use does not not accept an expression
2. if (condition) {use A;} else {use B;} doesn't work because condition isn't evaluated until runtime.
AND
3. my new solution doesn't work either UNLESS the condition can be evaluated at runtime. For example, if (-e filename) works, but if ($opt_t) does not.

SO, I am back trying to resolve this problem, which is:

How can I conditionally load a module based on a command line option? I would appreciate your advice.

This code appears to partially work. It appears that the require works (no errors), but the import fails (printing the imported variable is null).


#!/usr/bin/perl
$moduleName = "Reminderst.pm";
require $moduleName;
import $moduleName qw(@annualReminders);
print "Annual Reminders: $annualReminders[0]{subject}\n";
exit;
1

# The package
package Reminderst;
use Exporter();
@ISA=('Exporter');
# Explicitly export the following
@EXPORT=qw(@annualReminders @generalReminders);

@annualReminders=(
{
datestamp=>'080126',
recipient=>"Dick",
subject=>'Annual Reminder Test',
message=>'Annual Reminder Test.',
}
);


If you don't spot anything wrong in the code, can you suggest a method of debugging the problem? What can I examine? When running the Perl debugger, perl -d, s does not step into the perl code, only my script.

GN
 
I would do something like this if all you do is call one or two modules instead of any random module:

Code:
#!/usr/bin/perl
use strict;
use warnings;

BEGIN {
   my $moduleName = $ARGV[0] || die "Missing module argument";
   if ($moduleName eq 'Reminderst') {
      use Reminderst qw(@annualReminders);
   }
   elsif ($moduleName eq 'Reminders') {
      use Reminders qw(@annualReminders);
   }
   else {
      die "Can't seem to load the module: $moduleName";
   }
}
if (@annualReminders) {
   print "Annual Reminders: $annualReminders[0]{subject}\n";
}
else {
   print "Failed to find @annualReminders array";
} 
exit;
1

the BEGIN blocked is executed as soon as possible, before the rest of the code is compiled. In the module you may need to also use "our":

our (@annualReminders, @generalReminders);




------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
KevinADC: Thanks for the quick response. I ran ALL the code you provided and it unconditionally loads Reminders, regardless of the module specified on the command line.

I thought you had it -- back to the drawing board.

GN
 
change the "use" lines to require, example:

require "Reminderst.pm";

and see if that works.


------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
KevinADC: This works:

BEGIN {
my $moduleName = $ARGV[0] || die "Missing module argument";
if ($moduleName eq 'Reminderst') {
require Reminderst;
import Reminderst qw(@annualReminders);
}
elsif ($moduleName eq 'Reminders') {
require Reminders;
import Reminders qw(@annualReminders);
}
else {
die "Can't seem to load the module: $moduleName";
}
}

This is a good workaround. It would be nice to understand why this doesn't work.

$moduleName = "Reminderst.pm";
require $moduleName;
import $moduleName qw(@annualReminders);
print "Annual Reminders 0: $annualReminders[0]{subject}\n";
exit;

HOWEVER, maybe that can be a task for another day.

Thanks for your help.

GN
 
gnubie said:
# This works
require Reminderst;
import Reminderst qw(@annualReminders);
print "Annual Reminders 0: $annualReminders[0]{subject}\n";
exit;

# This gets "Can't locate Reminderst in @INC (@INC contains: C:/Perl/lib C:/Perl/site/lib .) at d:\perlscripts\reminder\reqtest.pl line 11."
$moduleName = "Reminderst";
require $moduleName;
import $moduleName qw(@annualReminders);
print "Annual Reminders 0: $annualReminders[0]{subject}\n";
exit;

# This gets no compile errors, but doesn't import arrays
$moduleName = "Reminderst.pm";
require $moduleName;
import $moduleName qw(@annualReminders);
print "Annual Reminders 0: $annualReminders[0]{subject}\n";
exit;

require works on a specific file name, and so must include the .pm extension. Import is a class method and so requires the class name (ie no .pm extension). That is why neither of the above two methods work. All you need is to explicitly include the .pm in the require statement.

Code:
[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]$moduleName[/blue] = [red]"[/red][purple]Reminderst[/purple][red]"[/red][red];[/red]
[url=http://perldoc.perl.org/functions/require.html][black][b]require[/b][/black][/url] [red]"[/red][purple][blue]$moduleName[/blue].pm[/purple][red]"[/red][red];[/red]
import [blue]$moduleName[/blue] [red]qw([/red][purple]@annualReminders[/purple][red])[/red][red];[/red]
[url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] [red]"[/red][purple]Annual Reminders  0: [blue]$annualReminders[/blue][0]{subject}[purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red]
[url=http://perldoc.perl.org/functions/exit.html][black][b]exit[/b][/black][/url][red];[/red]

- Miller

 
hmmm..... seems "import" is missing from the builtin functions list in the highlighter script. Probably because it is so rarely ever implictly used in a program.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
import isn't a built-in function. Its simply a common class method that is either defined or inherited by packages wishing to export. True, it's called by the built-in use function, but it's doesn't qualify as built-in strictly speacking.

However, if you made it link to the page defined for it in perldoc, that'd still be cool :)


- Miller
 
Yea, it has a man page, but the author of the highlighter did not include it in the built-in functions list and I failed to notice it was missing until now. I'll go ahead and add it. Did you ever get a chance to look at the highlighter scripts I sent you?

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
done:

Code:
[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]$moduleName[/blue] = [red]"[/red][purple]Reminderst[/purple][red]"[/red][red];[/red]
[url=http://perldoc.perl.org/functions/require.html][black][b]require[/b][/black][/url] [red]"[/red][purple][blue]$moduleName[/blue].pm[/purple][red]"[/red][red];[/red]
[url=http://perldoc.perl.org/functions/import.html][black][b]import[/b][/black][/url] [blue]$moduleName[/blue] [red]qw([/red][purple]@annualReminders[/purple][red])[/red][red];[/red]
[url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] [red]"[/red][purple]Annual Reminders  0: [blue]$annualReminders[/blue][0]{subject}[purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red]
[url=http://perldoc.perl.org/functions/exit.html][black][b]exit[/b][/black][/url][red];[/red]

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
KevinADC said:
Did you ever get a chance to look at the highlighter scripts I sent you?

Of course. And I immediately become obsessed with the fact that code was duplicated to support the preview ability, and had to stop looking at it to avoid distracting myself from my work even more than I normally do. However, I've noticed that you've since completely removed the preview, along with changing some of the formatting.

I approve :)

I still plan on playing with the script myself sometime soon. But I still have a ton of other projects lined up that have been waiting for much too long. At least they're fun projects.

- Miller
 
MillerH: Bravo. Well done. Subtle problem. Works great.
KevinADC: Thanks for your help too.

GN
 
You're welcome.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top