I have Perl code which relies on Term::ReadKey to get the terminal width. My installation is missing this module, so I want to provide a default if the module isn't present rather than throw an exception.
How can I conditionally use an optional module, without knowing ahead of time whether it is available.
# but only if the module is installed and exists
use Term::ReadKey;
...
How can I accomplish this?
Here's a bare-bones solution that does not require another module:
my $rc = eval
{
require Term::ReadKey;
Term::ReadKey->import();
1;
};
if($rc)
{
# Term::ReadKey loaded and imported successfully
...
}
Note that all the answers below (I hope they're below this one! :-) that use eval { use SomeModule } are wrong because use statements are evaluated at compile time, regardless of where in the code they appear. So if SomeModule is not available, the script will die immediately upon compiling.
(A string eval of a use statement will also work (eval 'use SomeModule';), but there's no sense parsing and compiling new code at runtime when the require/import pair does the same thing, and is syntax-checked at compile time to boot.)
Finally, note that my use of eval { ... } and $# here is succinct for the purpose of this example. In real code, you should use something like Try::Tiny, or at least be aware of the issues it addresses.
Check out the CPAN module Module::Load::Conditional. It will do what you want.
The classic answer (dating back to Perl 4, at least, long before there was a 'use') was to 'require()' a module. This is executed as the script is run, rather than when compiled, and you can test for success or failure and react appropriately.
if (eval {require Term::ReadKey;1;} ne 1) {
# if module can't load
} else {
Term::ReadKey->import();
}
or
if (eval {require Term::ReadKey;1;}) {
#module loaded
Term::ReadKey->import();
}
Note: the 1; only executes if require Term::... loaded properly.
And if you require a specific version of the module:
my $GOT_READKEY;
BEGIN {
eval {
require Term::ReadKey;
Term::ReadKey->import();
$GOT_READKEY = 1 if $Term::ReadKey::VERSION >= 2.30;
};
}
# elsewhere in the code
if ($GOT_READKEY) {
# ...
}
use Module::Load::Conditional qw(check_install);
use if check_install(module => 'Clipboard') != undef, 'Clipboard'; # class methods: paste, copy
using if pragma and Module::Load::Conditional core module.
check_install returns hashref or undef.
this module is also mentioned in the see also section of the pragma's documentation:
Module::Load::Conditional provides a number of functions you can use to query what modules are available, and then load one or more of them at runtime.
This is an effective idiom for loading an optional module (so long as you're not using it in a code base with sigdie handler),
use constant HAS_MODULE => defined eval { require Module };
This will require the module if available, and store the status in a constant.
You can use this like,
use constant HAS_READLINE => defined eval { require Term::ReadKey };
my $width = 80;
if ( HAS_READLINE ) {
$width = # ... code, override default.
}
Note, if you need to import it and bring in the symbols you can easily do that too. You can follow it up.
use constant HAS_READLINE => defined eval { require Term::ReadKey };
Term::ReadKey->import if HAS_READLINE;
This method uses constants. This has the advantage that if you don't have this module the dead code paths are purged from the optree.
I think it doesn't work when using variables.
Please check this link which explains how it can be used with variable
$class = 'Foo::Bar';
require $class; # $class is not a bareword
#or
require "Foo::Bar"; # not a bareword because of the ""
The require function will look for the "Foo::Bar" file in the #INC array and will complain about not finding "Foo::Bar" there. In this case you can do:
eval "require $class";
Related
Why, even after specifying subtract function in EXPORT_FAIL, am I able to access the function by defining it fully like mathematics::subtract? How can we completely make the function private?
package mathematics;
use Exporter;
#ISA = qw(Exporter);
#EXPORT = qw(add);
#EXPORT_FAIL = qw(subtract);
sub add() {
print("you can add numbers here"."\n");
}
sub subtract() {
print("you can subtract the numbers here"."\n");
}
1;
How can we completely make the function private???
You cannot. Perl doesn't have the concept of private or public.
You can however make it a lexical code reference and use that inside your code.
package Foo;
use strict;
use warnings;
my $_private = sub {
return "this is a secret";
}; # note the semicolon
sub bar {
return $_private->(); # call with reference syntax ->()
}
1;
As a lexical variable, it is now only accessible from within its scope. In this case, that scope is the file, not the package. So if you have multiple packages in one file, they can all see it. You cannot access it via a fully qualified name from outside the package.
By convention, things that should be handled as if they were private in Perl are named with a leading underscore _. That's how other developers know that something is not part of the public API of a module and that it's subject to change and should not be messed with. Of course that doesn't stop anybody from doing it, but generally there is no reason to stop them.
Also note that package names in Perl typically are written in camel case with the first letter being capitalised. Your package should be called Mathematics, and it should have use strict and use warnings.
From Perl 5.18, you can use lexical subroutines to achieve what you want. The documentation says this:
These subroutines are only visible within the block in which they are
declared, and only after that declaration:
# Include these two lines if your code is intended to run under Perl
# versions earlier than 5.26.
no warnings "experimental::lexical_subs";
use feature 'lexical_subs';
foo(); # calls the package/global subroutine
state sub foo {
foo(); # also calls the package subroutine
}
foo(); # calls "state" sub
my $ref = \&foo; # take a reference to "state" sub
my sub bar {
...
}
bar(); # calls "my" sub
p.s. Lexical subroutines are non-experimental from 5.26.
Is it possible to create global functions available across all namespaces like perl built-in functions?
First of all, "function" is the name given to Perl's named list operators, named unary operators and named nullary operators. They are visible everywhere because they are operators, just like ,, && and +. Subs aren't operators.
Second of all, you ask how to create a global sub, but all subs are already global (visible from everywhere) in Perl! You simply need to quality the name of the sub with the package if it's not in the current package. For example, Foo::mysub() will call my_sub found in package Foo from anywhere.
But maybe you want to be able to say mysub() instead of Foo::mysub() from everywhere, and that's a very bad idea. It violates core principles of good programming. The number of types of problems it can cause are too numerous to list.
There is a middle ground. A better solution is to create a sub that can be imported into the namespaces you want. For example, say you had the module
package Foo;
use Exporter qw( import );
our #EXPORT_OK = qw( my_sub );
our %TAGS = ( ALL => \#EXPORT_OK );
sub my_sub { ... }
1;
Then, you can use
use Foo qw( my_sub );
to load the module (if it hasn't already been loaded) and create my_sub in the current package. This allows it to call the sub as my_sub() from the package into which it was imported.
There is nothing simple that would allow one to somehow "register" user's subs with the interpreter, or some such, so that you could run them as builtins in any part of the program.
One way to get the behavior you ask for is to directly write to symbol tables of loaded modules. This has to be done after the modules have been loaded, and after subs that you add to those modules have been defined. I use INIT block in the example below.
Note that this has a number of weaknesses and just in general the idea itself is suspect to me, akin to extending the interpreter. Altogether I'd much rather write a module with all such subs and use standard approaches for good program design to have that module loaded where it needs to go.
Having said that, here is a basic demo
use warnings;
use strict;
use feature 'say';
use Data::Dump qw(dd pp);
use TestMod qw(modsub);
sub t_main { say "In t_main(), from ", __PACKAGE__ }
modsub("Calling from main::");
INIT {
no strict 'refs';
foreach my $pkg (qw(TestMod)) {
*{ $pkg . '::' . 'sub_from_main' } = \&t_main;
}
dd \%TestMod::;
}
This copies the reference to t_main from the current package (main::) into the symbol table of $pkg, under the name of sub_from_main, which can then be used with that name in that package.
For simplicity the name of the module is hardcoded, but you can use %INC instead, and whatever other clues you have, to figure out what loaded modules' stashes to add to.
The benefactor (or the victim?) module TestMod.pm
package TestMod;
use warnings;
use strict;
use feature 'say';
use Exporter qw(import);
our #EXPORT_OK = qw(modsub);
sub modsub {
say "In module ", __PACKAGE__, ", args: #_";
say "Call a sub pushed into this namespace: ";
sub_from_main();
}
1;
The name of the added sub can be passed to modules as they're loaded, instead of being hardcoded, in which case you need to write their import sub instead of borrowing the Exporter's one.
There are also modules that allow one to add keywords, but that's no light alternative.
The answer seems to be no, but you can impliment most of the behaivior that you want by using the symbol table *main::main:: to define a subroutine in all the namespaces.
use strict;
use warnings;
use Data::Dump qw(dd);
my $xx = *main::main::;
package A;
sub test {
printf "A::%s\n", &the_global;
}
package B;
sub the_global
{
"This is B::the_global";
}
sub test {
printf "B::%s\n", &the_global;
}
package main;
my $global_sub = sub { "The Global thing" };
for my $NS (keys %$xx) {
if ($NS =~ /^[A-Z]::$/) {
my $x = $NS . 'the_global';
if (defined &$x) {
printf "Skipping &%s\n", $x;
} else {
printf "Adding &%s\n", $x;
no strict 'refs';
*$x = $global_sub;
}
}
}
A::test;
This will not work on packages that are not referenced at all before the for loop above is run. But this would only happen if a require, use or package was eval'd after the code started running.
This is also still a compiler issue! You either need to refer to the global function as the_global() or &the_global if you are (as you should be) using use strict.
Sorry for my late response and thank you all for yours detailed answers and explanations.
Well.. I understood the right answer is: IT'S NOT POSSIBLE!
I'm mantaining a Perl framework used by some customers, and that framework exports some specialized subs (logging, event handling, controllers for hardware devices, domain specific subs and so). That's why I tried to figure out how to prevent the developers from importing my subs in all their packages.
I have Perl code which relies on Term::ReadKey to get the terminal width. My installation is missing this module, so I want to provide a default if the module isn't present rather than throw an exception.
How can I conditionally use an optional module, without knowing ahead of time whether it is available.
# but only if the module is installed and exists
use Term::ReadKey;
...
How can I accomplish this?
Here's a bare-bones solution that does not require another module:
my $rc = eval
{
require Term::ReadKey;
Term::ReadKey->import();
1;
};
if($rc)
{
# Term::ReadKey loaded and imported successfully
...
}
Note that all the answers below (I hope they're below this one! :-) that use eval { use SomeModule } are wrong because use statements are evaluated at compile time, regardless of where in the code they appear. So if SomeModule is not available, the script will die immediately upon compiling.
(A string eval of a use statement will also work (eval 'use SomeModule';), but there's no sense parsing and compiling new code at runtime when the require/import pair does the same thing, and is syntax-checked at compile time to boot.)
Finally, note that my use of eval { ... } and $# here is succinct for the purpose of this example. In real code, you should use something like Try::Tiny, or at least be aware of the issues it addresses.
Check out the CPAN module Module::Load::Conditional. It will do what you want.
The classic answer (dating back to Perl 4, at least, long before there was a 'use') was to 'require()' a module. This is executed as the script is run, rather than when compiled, and you can test for success or failure and react appropriately.
if (eval {require Term::ReadKey;1;} ne 1) {
# if module can't load
} else {
Term::ReadKey->import();
}
or
if (eval {require Term::ReadKey;1;}) {
#module loaded
Term::ReadKey->import();
}
Note: the 1; only executes if require Term::... loaded properly.
And if you require a specific version of the module:
my $GOT_READKEY;
BEGIN {
eval {
require Term::ReadKey;
Term::ReadKey->import();
$GOT_READKEY = 1 if $Term::ReadKey::VERSION >= 2.30;
};
}
# elsewhere in the code
if ($GOT_READKEY) {
# ...
}
use Module::Load::Conditional qw(check_install);
use if check_install(module => 'Clipboard') != undef, 'Clipboard'; # class methods: paste, copy
using if pragma and Module::Load::Conditional core module.
check_install returns hashref or undef.
this module is also mentioned in the see also section of the pragma's documentation:
Module::Load::Conditional provides a number of functions you can use to query what modules are available, and then load one or more of them at runtime.
This is an effective idiom for loading an optional module (so long as you're not using it in a code base with sigdie handler),
use constant HAS_MODULE => defined eval { require Module };
This will require the module if available, and store the status in a constant.
You can use this like,
use constant HAS_READLINE => defined eval { require Term::ReadKey };
my $width = 80;
if ( HAS_READLINE ) {
$width = # ... code, override default.
}
Note, if you need to import it and bring in the symbols you can easily do that too. You can follow it up.
use constant HAS_READLINE => defined eval { require Term::ReadKey };
Term::ReadKey->import if HAS_READLINE;
This method uses constants. This has the advantage that if you don't have this module the dead code paths are purged from the optree.
I think it doesn't work when using variables.
Please check this link which explains how it can be used with variable
$class = 'Foo::Bar';
require $class; # $class is not a bareword
#or
require "Foo::Bar"; # not a bareword because of the ""
The require function will look for the "Foo::Bar" file in the #INC array and will complain about not finding "Foo::Bar" there. In this case you can do:
eval "require $class";
I have a variable $x which currently has a local scope in A.pm and I want to use the output of $x (which is usually PASSED/FAILED) in an if else statement in B.pm
Something like below
A.pm:
if (condition1) { $x = 'PASSED'; }
if (condition2) { $x = 'FAILED'; }
B.pm:
if ($x=='PASSED') { $y=1; } else { $y=0; }
I tried using require ("A.pm"); in B.pm but it gives me an error global symbol requires an explicit package name which means it is not able to read the variable from require. Any inputs would help
I have a variable $x which currently has a local scope in A.pm and I want to use the output of $x (which is usually PASSED/FAILED) in an if else statement in B.pm
We could show you how to do this, but this is a really bad, awful idea.
There's a reason why variables are scoped, and even global variables declared with our and not my are still scoped to a particular package.
Imagine someone modifying one of your packages, and not realizing there's a direct connection to a variable name $x. They could end up making a big mess without even knowing why.
What I would HIGHLY recommend is that you use functions (subroutines) to pass around the value you need:
Local/A.pm
package Local::A;
use strict;
use warnings;
use lib qw($ENV{HOME});
use Exporter qw(import);
our #EXPORT_OK = qw(set_condition);
sub set_condition {
if ( condition1 ) {
return "PASSED";
elsif ( condition2 ) {
return "FALSED";
else {
return "Huh?";
}
1;
Here's what I did:
I can't use B as a module name because that's an actual module. Therefore, I used Local::B and Local::A instead. The Local module namespace is undefined in CPAN and never used. You can always declare your own modules under this module namespace.
The use lib allows me to specify where to find my modules.
The package command gives this module a completely separate namespace. This way, variables in A.pm don't affect B.pm.
use Exporter allows me to export subroutines from one module to another. #EXPORT_OK are the names of the subroutines I want to export.
Finally, there's a subroutine that runs my test for me. Instead of setting a variable in A.pm, I return the value from this subroutine.
Check your logic. Your logic is set that $x isn't set if neither condition is true. You probably don't want that.
Your module can't return a zero as the last value. Thus, it's common to always put 1; as the last line of a module.
Local/B.pm
package Local::B;
use lib qw($ENV{HOME});
use Local::A qw(set_condition);
my $condition = set_contition();
my $y;
if ( $condition eq 'PASSED' ) { # Note: Use `eq` and not `==` because THIS IS A STRING!
$y = 1;
else {
$y = 0;
}
1;
Again, I define a separate module namespace with package.
I use Local::A qw(set_condition); to export my set_condition subroutine into B.pm. Now, I can call this subroutine without prefixing it with Local::A all of the time.
I set a locally scoped variable called $condition to the status of my condition.
Now, I can set $y from the results of the subroutine set_condition. No messy need to export variables from one package to another.
If all of this looks like mysterious magic, you need to read about Perl modules. This isn't light summer reading. It can be a bit impenetrable, but it's definitely worth the struggle. Or, get Learning Perl and read up on Chapter 11.
After you require A;, you can then access the variable by giving it an explicit package name like the error message says.
in B.pm:
my $y = $A::x eq 'PASSED ? 1 : 0
The variable $x will have to be declared with our instead of my.
Finally, use eq instead of == for doing string comparisons.
I have a Perl script which uses a not-so-common module, and I want it to be usable without that module being installed, although with limited functionality. Is it possible?
I thought of something like this:
my $has_foobar;
if (has_module "foobar") {
<< use it >>
$has_foobar = true;
} else {
print STDERR "Warning: foobar not found. Not using it.\n";
$has_foobar = false;
}
You can use require to load modules at runtime, and eval to trap possible exceptions:
eval {
require Foobar;
Foobar->import();
};
if ($#) {
warn "Error including Foobar: $#";
}
See also perldoc use.
Consider the if pragma.
use if CONDITION, MODULE => ARGUMENTS;
I recommend employing Module::Load so that the intention is made clear.
Edit: disregard the comments, Module::Load is in core.
Another approach is to use Class::MOP's load_class method. You can use it like:
Class::MOP::load_class( 'foobar', $some_options )
It throws an exception so you'll have to catch that. More info here.
Also, while this isn't necessarily on every system Class::MOP is awfully useful to have and with Moose becoming more prevalent every day it likely is on your system.