Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

Conditional compile-time magic (RE: Checking to see if a particular Module is installed)

by tye (Sage)
on Aug 11, 2000 at 20:25 UTC ( #27533=note: print w/replies, xml ) Need Help??

in reply to RE: RE: RE: RE: Checking to see if a particular Module is installed
in thread Checking to see if a particular Module is installed

[ Aside: Yes, I discussed that briefly in my node. That is why I said that I didn't get your point (in the context of the discussion). Also, I assumed that you must have been getting at something else since your reply included code with exactly the same problem (as did your own code earlier in the thread). My node explicitly mentions not being able to use imported subs via barewords, so using that specific case as an example of where I was wrong doesn't make much sense. :) And you are wrong about me not having been burned. I've had quite a bit of fun battling conditional module use (and conditional constant definition) with compile-time magic. Now back to the technical discussion. ]

You can't use a module's compile-time magic (like prototypes) when you conditionally use the module, unless you conditionally compile all of the code that uses that magic. Like I said, there are ways to do this, but none of them are good.

There is only one way that I've actually used that survived very long. You can, at compile time, conditionally compile a sub that makes use of the compile-time magic. For example:

BEGIN { my $code= '...some work-around for not having GD...'; if( eval { require GD } ) { $code= '...code that uses GD...'; } eval "sub mySub { $code }; 1 " or die "$@"; }

But doing this in order to use bareword constants is rarely worth it (though it does give you compile-time checking for half of your typos).

So you are often better to just not use the compile-time magic. For example, consider this pretend module that makes other uses of prototypes:

package Pretend; use base qw(Exporter); our @EXPORT_OK= qw( sorter hasher ); sub sorter(&@); sub hahser(\%); #[...]

You might try to work-around a possible lack of this module via:

my $got_Pretend; BEGIN { if( $got_Pretend= eval { require Pretend } ) { Pretend->import( qw( sorter hasher ) ); } else { require WorsePretendWorkAround; WorsePretendWorkAround->import( qw( comparer worse_hasher ) ); } } #[...] if( $got_Pretend ) { @list= sorter { $_[0] <=> $_[1] } hasher %hash; } else { @list= sort \&comparer worse_hasher(\%hash); }

And if you never bother to test your code when the Pretend module isn't installed, then you might think you've got a pretty good fix. However, this code will just fail to compile if there is no Pretend module (well, it certainly will if you use strict, but you always do that). If that were an okay failure mode, then you might as well just write use Pretend!

But you can work-around this possible lack of compile-time magic by just avoiding your use of the magic:

if( $got_Pretend ) { @list= sorter( sub { $_[0] <=> $_[1] }, &hasher(\%hash) ); } else { @list= sort \&comparer worse_hasher(\%hash); }

Unfortunately, this solution won't tell you when the interface to hasher changes. But there are enough problems with using current Perl prototypes for this kind of checking that you probably won't ever run into that.

Another solution that sounds very nice but that I've never actually used, is to put the module-dependant code into a separate file and require that file (at compile time) if the module is present.

Anyway, the one simple thing that everyone should remember about this problem is:

  • If you conditionally use a module, then you need to test your code both with and without the module!

(And if you conditionally use N modules, then you need to test your code in the 2^N cases of module availability!)

        - tye (but my friends call me "Tye")
  • Comment on Conditional compile-time magic (RE: Checking to see if a particular Module is installed)
  • Select or Download Code

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://27533]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (2)
As of 2022-07-01 22:16 GMT
Find Nodes?
    Voting Booth?
    My most frequent journeys are powered by:

    Results (102 votes). Check out past polls.