Re: using 'use' conditionally (require instead of use)
by ybiC (Prior) on Nov 05, 2002 at 00:50 UTC
|
If I'm not mistaken, you want to require instead of use in your eval block. Here's how I did similarly a while back:
my $have_SWE;
BEGIN {
$have_SWE = 0;
eval { require Spreadsheet::WriteExcel };
unless ($@) {
Spreadsheet::WriteExcel->import();
$have_SWE = 1;
}
}
if ($have_SWE == 1) { ... }
If memory serves, I picked that up from something merlyn once said or posted.
cheers,
Don
striving toward Perl Adept
(it's pronounced "why-bick")
Update:
Super Search for "module installed" is what lead me to this thread, where I learnt of BEGIN, eval, and require.
Update:
After discussing with brother BUU, the lone advantage I can see of BEGIN... eval is that it allows you to include a more user-friendly message in the event that Tk isn't installed. As always, Wiser Monks Than I may very well rightly say that I'm fullabeans. {grin}
Untested, but perhaps a wee bit cleaner than my original code example:
my $have_Tk;
BEGIN {
$have_Tk = 0;
eval { require Tk };
$have_Tk = 1 unless ($@);
}
if ($have_Tk == 1) { ... }
| [reply] [d/l] [select] |
|
Why bother evaling? Just do if($opt_g){require Tk;}
| [reply] [d/l] |
|
| [reply] |
|
|
When I switch the 'use' to a 'require', I can indeed determine if the module is not installed and catch that.
However, if the module *is* installed, the Tk code fails to function. There are no errors or anything - the script just exits. I actually placed a 'print' after the MainLoop call, and I see the print output.
It seems to make no difference whether I call Tk->import;
It seems to make no difference if I place Tk:: before the tk subroutines.
bizarre...
| [reply] |
Re: using 'use' conditionally
by LTjake (Prior) on Nov 05, 2002 at 01:22 UTC
|
There's also the lovely if module.
Example:
use constant DEBUG => 1;
use if (DEBUG), 'CGI::Carp' => 'fatalsToBrowser';
-- Rock is dead. Long live paper and scissors! | [reply] [d/l] |
Re: using 'use' conditionally
by petral (Curate) on Nov 05, 2002 at 01:41 UTC
|
| [reply] |
Re: using 'use' conditionally
by broquaint (Abbot) on Nov 05, 2002 at 11:04 UTC
|
Although not directly applicable to the problem at hand (which can be solved with a require) there is the if module (core in 5.8.0) which will use a Perl module if a condition holds. The only problem with this is that it happens at compile time, so couldn't be directly applied in your particular case.
HTH
_________ broquaint
update: doh, just noticed LTjake's node above. note to self - recaffeinate head before posting | [reply] |
Re: using 'use' conditionally
by Anonymous Monk on Nov 05, 2002 at 10:34 UTC
|
Have a look in the Perl Cookbook : "Recipe 12.2 Trapping Errors in require or use".
It propose to trap problems with require using eval.
It also says to do it in a BEGIN block (compile time versus run time).
| [reply] |
Re: using 'use' conditionally
by dilbert (Novice) on Nov 05, 2002 at 11:03 UTC
|
The error output of the eval block is caught in the $@ variable, that's why you don't see any error message. Leave out the 'die', and try this: if ($@){
die "Tk not installed. Can't run GUI. Error returned: $@\n";
}
| [reply] [d/l] |
Re: using 'use' conditionally
by blssu (Pilgrim) on Nov 05, 2002 at 16:59 UTC
|
You can't always replace 'use' with 'require' because they work slightly differently. 'use' works at compile time and also imports stuff into your code. 'require' works at run time and never imports stuff.
This example isn't exactly like your problem, but I think it might be useful anyways.
BEGIN {
if ($^O eq 'MSWin32') {
eval "use APDM::ConfigWin32";
print $@ if ($@);
}
else {
eval "use APDM::ConfigUnix";
print $@ if ($@);
}
}
| [reply] [d/l] |
|
If you care that much about importing from the module:
if($opt_g)
{
require Tk;
Tk->import;
}
Difference goes away! wow. | [reply] [d/l] |
|
Difference goes away! wow.
BUU is right. Additionally, blssu, you don't need to import if you're going to use the OO interface of whichever module you required... because good OO interfaces don't export their methods.
blyman
setenv EXINIT 'set noai ts=2'
| [reply] |
|
Sure, that's pretty close to what 'use' does now, but the 'eval' helps future-proof your code. The hand-rolled import isn't clever, it's just extra work. Laziness is one of the three pillars...
The common efficiency and security disadvantages of 'eval' aren't issues here because (1) run-time 'require' must do an 'eval' eventually anyway, and (2) the 'eval' uses a string constant that is easy to understand and verify.
| [reply] |
whatif { Re: using 'use' conditionally} ifonly { true; }
by mattr (Curate) on Nov 05, 2002 at 13:35 UTC
|
I was intrigued by the Whatif modules with its patented Guardian Angel (TM) technology. This is neat!
Of course Switch.pm's bad mojo got me into trouble recently so I am not going to be the first to implement in a production environment.. unless my first step is to surround the entire program with a whatif {} ifonly {} clause!
| [reply] |
Re: using 'use' conditionally
by mousey (Scribe) on Nov 05, 2002 at 16:44 UTC
|
| [reply] [d/l] |
Re: using 'use' conditionally
by dash2 (Hermit) on Nov 06, 2002 at 17:31 UTC
|
Lots of people have pointed out BEGIN, "use if" and "require".
Another point is that (unless your program is very simple) you probably don't want to include the Tk interface and the command line interface in the same packages.
Instead do something like this:
my $iface = $opt_g ? new MyInterface::Tk : new MyInterface::CommandLin
+e;
The two MyInterface subclasses provide different ways of doing the same thing... so then you can write:
$iface->notify("Your flies are down");
$iface->ask("Do you want to zip them up?", 'Y', 'N');
This separates your interface code nice and cleanly from the rest of your program.
Of course, you still have to be careful what you require, because if Tk isn't installed, then MyInterface::Tk will presumably die on compilation.
dave hj~ | [reply] [d/l] [select] |
Re: using 'use' conditionally
by BUU (Prior) on Nov 06, 2002 at 02:12 UTC
|
This is basically a reply to everyone who suggested something like:
eval { use Tk; }
if($@){ goto &cli }
else { MainLoop(); }
And the problem is that it takes control away from the user. What if i have Tk, but i don't want to use the bloody tk interface? | [reply] [d/l] |
|
BUU asks : What if i have Tk, but i don't want to use the bloody tk interface?
Then you probably wouldn't be specifying it using the -g option, as given in the original question.
| [reply] |
Re: using 'use' conditionally
by xafwodahs (Scribe) on Dec 02, 2002 at 19:04 UTC
|
Here is a test script. Run it with a -g as the first parameter.
On a machine without Tk, it will correctly die.
On a machine with Tk, it *should* bring up a simple Tk window, but it exits instead. If I replace the 'require' and 'import' with the 'use', then it works.
if ($ARGV[0] =~ /-g/) {
# do gui
die "You need Tk." unless (eval("require Tk;"));
#use Tk;
require Tk;
Tk->import;
$mw = MainWindow->new;
$mw->Button(-text=>"EXIT",
-command=>sub{exit})->pack(-side=>"bottom",
-fill=>"both");
MainLoop;
print "gui done.\n";
} else {
# do non-gui
print "non-gui stuff\n";
}
| [reply] [d/l] |
|
| [reply] [d/l] [select] |
Re: using 'use' conditionally
by pizza_milkshake (Monk) on Nov 07, 2002 at 03:09 UTC
|
use eval and check $@... there's an example in The Perl Cookbook by O'Reilly
perl -e'$_=q#: 13_2: 12/"{>: 8_4) (_4: 6/2"-2; 3;-2"\2: 5/7\_/\7: 12m m::#;s#:#\n#g;s#(\D)(\d+)#$1x$2#ge;print'
| [reply] |