Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

comment on

( #3333=superdoc: print w/replies, xml ) 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:

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")

In reply to Conditional compile-time magic (RE: Checking to see if a particular Module is installed) by tye
in thread Checking to see if a particular Module is installed by skazat

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or or How to display code and escape characters are good places to start.
Log In?

What's my password?
Create A New User
Domain Nodelet?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (3)
As of 2022-07-04 00:02 GMT
Find Nodes?
    Voting Booth?

    No recent polls found