Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

ferreira (5993)

ferreira
  (email not shown publicly)
http://www.ferreira.triang.net/

Just another Brazilian Perl hacker.

Journal of ferreira (5993)

Monday July 16, 2007
01:22 PM

The trap of eval { use Foo }

[ #33821 ]

When writing tests, the general boilerplate for optional tests which are totally skipped when a module is not installed, is:

eval "use Test::Pod 1.18";
plan skip_all => "Test::Pod 1.18 required for testing POD" if $@;

And then we remember that "eval STRING" must not be used where "eval BLOCK" may be enough. So I was tempted to write (and did it a few times):

eval { use Test::Pod 1.18 };
plan skip_all => "Test::Pod 1.18 required for testing POD" if $@;

This has the horrible disadvantage of not working ;-) The essential difference of "eval STRING" and "eval BLOCK" are that compilation issues are deferred in the former while happening earlier (at compile time) in the later. But the "use Foo" thing is a compile-time statement and then, as soon as Perl compiles the code, it executes the equivalent BEGIN block which will thus fail noisily.

$ perl -e "eval { use Foo };"
Can't locate Foo.pm in @INC (@INC contains: ... ) at -e line 1.
BEGIN failed--compilation aborted at -e line 1.

In turn, eval "use Foo" will do the right thing, executing the loading of the module at the opportune moment and storing the error message in $@ if that's the case. If you insist, you may use "eval BLOCK" yet in an expanded form:

eval {
    require Foo;
    Foo->VERSION(2.3);
    Foo->import
}

(That's exactly how rjbs did it in one of his recent distributions.)

Well, of course you knew that. But now that I wrote it, I don't even have to articulate it again some next time.

And now a shameless plug: one of the reasons Devel::Hide was written was to allow me to test code which should fail gracefully when certain modules are not present. Even in a machine, where those modules are indeed installed.

$ perl -Mblib t/99_pod.t
1..30
ok 1 - Foo.pm
...
ok 30 - Bar.pm

$ perl -Mblib -MDevel::Hide=Test::Pod t/99_pod.t
Devel::Hide hides Test/Pod.pm
1..0 # Skip Test::Pod 1.18 required for testing POD

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.