I've got a Perl script that I'm trying to make compatible with two different Perl environments. To work around the two different versions of Socket I have, I'm doing a little hackery with require and import. I've got it working, but I'm not happy with the behavior.
Mod.pm:
package Mod;
use base 'Exporter';
our @EXPORT = qw( MAGIC_CONST );
sub MAGIC_CONST() { 42; }
test.pl:
use Mod;
#require Mod;
#import Mod;
printf "MAGIC_CONST = ". MAGIC_CONST ."\n";
printf "MAGIC_CONST = ". MAGIC_CONST() ."\n";
Outputs:
MAGIC_CONST = 42
MAGIC_CONST = 42
But using the 'require' and 'import' instead, I get this:
Output:
MAGIC_CONST = MAGIC_CONST
MAGIC_CONST = 42
So the question is: Is there a clean way I can get the normal behavior of the constants? I can certainly do sub MAGIC_CONST { Mod::MAGIC_CONST(); }
but that's pretty ugly.
What I'm actually doing is something like this:
use Socket;
if ($Socket::VERSION > 1.96) {
import Socket qw(SO_KEEPALIVE); # among others
setsockopt($s, SOL_SOCKET, SO_KEEPALIVE); # among others
}
The reason the require
version prints MAGIC_CONST
instead of 42
is because use
is what tells perl to import the symbols from one module to another. Without the use
, there is no function called MAGIC_CONST
defined, so perl interprets it as a string instead. You should use strict
to disable the automatic conversion of barewords like that into strings.
#!/usr/bin/env perl
no strict;
# forgot to define constant MAGIC_CONST...
print 'Not strict:' . MAGIC_CONST . "\n";
produces
Not strict:MAGIC_CONST
But
#!/usr/bin/env perl
use strict;
# forgot to define constant MAGIC_CONST...
print 'Strict:' . MAGIC_CONST . "\n";
Produces an error:
Bareword "MAGIC_CONST" not allowed while "strict subs" in use at ./test.pl line 4. Execution of ./test.pl aborted due to compilation errors.
So if you want to use one module's functions in another, you either have to import them with use
, or call them with the full package name:
package Foo;
sub MAGIC_CONST { 42 };
package Bar;
print 'Foo from Bar: ' . Foo::MAGIC_CONST . "\n";
Foo from Bar: 42
It's usually best to avoid conditionally importing things. You could resolve your problem as follows:
use Socket;
if ($Socket::VERSION > 1.96) {
setsockopt($s, SOL_SOCKET, Socket::SO_KEEPALIVE);
}
If you truly want to import, you still need to do it at compile-time.
use Socket;
use constant qw( );
BEGIN {
if ($Socket::VERSION > 1.96) {
Socket->import(qw( SO_KEEPALIVE ));
} else {
constant->import({ SO_KEEPALIVE => undef });
}
}
setsockopt($s, SOL_SOCKET, SO_KEEPALIVE) if defined(SO_KEEPALIVE);