|Pathologically Eclectic Rubbish Lister|
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||Need Help??|
[ 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:
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:
You might try to work-around a possible lack of this module via:
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:
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:
(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")