Making a perl module optional?

R

Richard

Hi there,

Is there any way to make the requirement of a module optional? The
reason I ask is that my application can show some additional
functionality but only if a relativily unknown module is installed (and
the many pre-requisits it has) too.

As such, I don't want to prevent people who don't have this installed
from using the application - albeit in its limited form.

Is there any way to detect whether this module is installed and then,
based on that, enable/disable certain parts of my perl application
associated with it?

Many thanks in advance,

Richard.
 
P

Paul Lalli

Richard said:
Is there any way to detect whether this module is installed and then,
based on that, enable/disable certain parts of my perl application
associated with it?

Attempt to load the module within an eval{} block, and then check for
errors (eval{} is Perl's way of doing a try/catch). If there's an
error, set your global flag to a false value, otherwise set it to a
true value.

Depending on your needs, you may or may not want to wrap the whole
thing in a BEGIN{} block:

Example:
#!/usr/bin/perl
use strict;
use warnings;

BEGIN {
eval {
#separate out the two steps of 'use' - otherwise this
#happens at compile time.
require Foo;
Foo->import();
};
if ($@){ #check for an error in previous eval{}
print "Foo not loaded; continuing without additional
functionality\n";
$main::use_foo = 0;
} else {
print "Foo loaded. Using Foo's functionality\n";
$main::use_foo = 1;
}
}

#main...

our $use_foo;

#some code...
if ($use_foo){
print "Here we'll do something with Foo\n";
} else {
print "Too bad you don't have Foo! This'd be really cool!\n";
}
#more code...

__END__

Hope this helps,
Paul Lalli
 
A

Average_Joe

Is there any way to make the requirement of a module optional? The
reason I ask is that my application can show some additional
functionality but only if a relativily unknown module is installed (and
the many pre-requisits it has) too.

As such, I don't want to prevent people who don't have this installed
from using the application - albeit in its limited form.

Is there any way to detect whether this module is installed and then,
based on that, enable/disable certain parts of my perl application
associated with it?

Lots of ways, but the general idea is to place it in an eval { .. }
block.

This can be trickier than it seems, because your application may
or may not have logic surrounding the modules. A _lot_ of how you
do it will depend on how your main program is designed.

My personal favorite is to place the stuff in a package and then
use the "driver/factory" approach:

sub my_factory {
my($file) = ... # Get $file/$package from some place, config, etc..
my($package) = ... # Get $package from some place.

# Could also use the wrapped eval { } block and test for failure.
# Doesn't work if the underlying implementation changes, but that
# may be OK.

if($file){
require($file);
return($package->new());
}else{
# Something that handles "Can't do it" situations.
return(My::Default::Implementation->new());
}
}

Where My::Default::Implementation is just a package that says
"I'm sorry, I can't do that" with it's methods. Of course, that
only works with objects, require() doesn't call import for you.

Could also return an empty list if not available, but, then your
application has to test for that each time. :-/

"My::Default::Implementation" could just have AUTOLOAD auto-generate methods
that die with an error message (or reference, or however you want to do it,
example: die "unsupported operation\n";

$drv = my_factory(); # Get object that may do optional things, or, handle
# cases where it can't do optional things.

while($event_loop_if_you_have_one){
eval {

... do stuff ...

};
if($@ eq "unsupported operation\n"){
print "Sorry, no can do!\n";
}else{
die $@; # Pass it up the chain.
}
}

NOTE: eval using {} NOT "".

Having optional modules can really burden the application, cluttering
up the code with tons of "if($optional_is_supported) { .. }" chunks.

Jamie
 
A

Anno Siegel

Richard said:
Hi there,

Is there any way to make the requirement of a module optional? The
reason I ask is that my application can show some additional
functionality but only if a relativily unknown module is installed (and
the many pre-requisits it has) too.

As such, I don't want to prevent people who don't have this installed
from using the application - albeit in its limited form.

Is there any way to detect whether this module is installed and then,
based on that, enable/disable certain parts of my perl application
associated with it?

Detecting whether a module is installed is best done by trying to
load it (this has been discussed in other followups).

Here is a slightly different approach. If your module can optionally
make use of some module Aux, require the user to "use Aux" before they
load your module. Then in your module, test if $Aux::VERSION is defined
and proceed accordingly. The "if" pragma can be useful here:

use if defined $Aux::VERSION Aux => qw( ...);

in case you need to import functions or otherwise activate the
Aux->import method. See "perldoc if".

That requires more action from the user than automatically loading the
module if it is installed, but it makes the difference visible near the
"use" statement.

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top