perl use vs require and import, constants are only functions - perl

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

Adam's answer gives a good explanation of what is going on and how to get the desired behavior. I am going to recommend not using constant.pm to define symbolic names for constants. A fairly nice looking and convenient alternative with fewer gotchas is to use constants defined using Const::Fast and allow them to be imported.
In addition, by using Importer in the module which wants to import the constants, the module that defines the constants can avoid inheriting Exporter's heavy baggage, or having to use Exporter's import.
The fact that Const::Fast allows you to define real constant arrays and hashes is a bonus.
For example:
package MyConstants;
use strict;
use warnings;
use Const::Fast;
use Socket;
const our #EXPORT => ();
const our #EXPORT_OK => qw(
%SOCKET_OPT
);
const our %SOCKET_OPT => (
keep_alive => ($Socket::VERSION > 1.96) ? Socket::SO_KEEPALIVE : undef,
);
__PACKAGE__;
__END__
Using these constants in a script:
#!/usr/bin/env perl
use strict;
use warnings;
use Socket;
use Importer 'MyConstants' => qw( %SOCKET_OPT );
if ( defined $SOCKET_OPT{keep_alive} ) {
setsockopt($s, SOL_SOCKET, $SOCKET_OPT{keep_alive});
}
As I note in my blog post:
f I want to read the constants from a configuration file, that's trivial. If I want to export them to JSON, YAML, INI, or whatever else, that's also trivial. I can interpolate them willy-nilly.
For those who have taken seriously Exporter's stance against exporting variables, this takes some getting used to. Keep in mind that the admonition is there to make sure you don't write code that willy nilly modifies global variables. However, in this case, the variables we are exporting are not modifiable. Maybe you can convince yourself that the concern really does not apply in this instance. If you try to refer to a non-existent constant, you get an error (albeit during run time) ...
In most cases, the benefits of this approach outweigh the speed penalty of not using constant.pm.

Related

Prototype mismatch: sub main::any: none vs (&#) at Exporter.pm

use Dancer2;
use List::Util qw(any);
sub use_any_subroutine {
foreach my $foo (#$foo_array) {
next unless any { $_ == $foo->id } #hello_world;
}
return;
}
there is a conflict with using List::Util and throwing a warning
Prototype mismatch: sub main::any: none vs (&#) at Exporter.pm(...).
i found a solution that is we can use List::Util::any instead of importing it before use,but i want to import it once,so how to avoid this warning
Thanks very much for comments.
There are a few possible solutions
Note that I'm using the core List::Util module here, because it also contains an any function, and shouldn't need installing on most recent releases of perl
As you have said yourself, you could fully-qualify the subroutine instead of importing it, and use List::Util::any
You could disable the import of any from Dancer2 by using
use Dancer2 '!any'
which will work as long as you never need Dancer2's any to write your code
You could also use first instead of any from List::Util, which returns the first element of the list for which the block returns a true value, and will work fine as long as everything in your list is true
Another alternative is to import any from List::Util with a different name
BEGIN {
require List::Util;
*my_any = \&List::Util::any;
}
and now you have a subroutine my_any that behaves exactly as the original any from List::Util but doesn't clash with the operator of the same name from Dancer2
Both Dancer2 and List::MoreUtils export an any function into your namespace.
For Dancer2, it's part of its DSL and is used as a route definition that matches any HTTP verb on incoming requests.
Defines a route for multiple HTTP methods at once
The List::MoreUtils one is like a grep instead.
Returns a true value if any item in LIST meets the criterion given through BLOCK.
The warning you are seeing is because you have imported the Dancer2 one first, so Perl learned about the prototype of that one. Then you imported the one from List::MoreUtils, which overwrote &main::any in your namespace main::, but the prototype is still there.
You can avoid importing any from Dancer2.
use Dancer2 qw( !any );
use List::MoreUtils qw( any );
get '/' => sub {
my #foo = ( 1, 2, 3 );
return List::MoreUtils::any { $_ == 2 } #foo;
};
dance;
Or you can avoid importing any from List::MoreUtils (using List::MoreUtils::any instead of any).
use Dancer2;
use List::MoreUtils qw( );
get '/' => sub {
my #foo = ( 1, 2, 3 );
return List::MoreUtils::any { $_ == 2 } #foo;
};
dance;
It is impossible to be sure without seeing more of your program, but at a guess, you have declared your own subroutine sub any as well as trying to import it from List::MoreUtils.
You need only the use statement.

How to dynamically avoid 'use module' to reduce memory footprint

Given the following module:
package My::Object;
use strict;
use warnings;
use My::Module::A;
use My::Module::B;
use My::Module::C;
use My::Module::D;
...
1;
I would like to be able to call My::Object in the next 2 scenarios:
Normal use
use My::Object;
My::Module->new();
Reduced memory use. Call the same object but with a condition or a flag telling the object to skip the use modules to reduce memory usage. Somehow like:
use My::Object -noUse;
My::Module->new();
If tried the Perl if condition without success.
The problem I'm having it's with big objects with a lot of uses, then only loading this object consumes a lot of RAM. I know I can refactor them but it will be wonderful if somehow I can avoid these uses when I'm sure none of them is used on the given scenario.
One solution will be to replace all uses with requires on all places when the modules are needed, but I don't see convenient when some of them are used in a lot of methods.
Any ideas?
Thanks
The native pragma autouse will load modules needed when plain subroutines are called:
use autouse 'My::Module::A' => qw(a_sub);
# ... later ...
a_sub "this will dynamically load My::Module::A";
For proper OO methods, Class::Autouse will load modules (classes) when methods are called:
use Class::Autouse;
Class::Autouse->autouse( 'My::Module::A' );
# ... later ...
print My::Module::A->a_method('this will dynamically load My::Module::A');
What I think you're looking for is perhaps require - require is evaluated later so you can use it successfully in a conditional:
if ( $somecondition ) {
require Some::Module;
}
Of course, you won't be able to do Some::Module->new() if you've not loaded it - there's just no way around that.
Where use is triggered at compile time (and thus will trigger warnings under perl -c if the module is unavailable) require happens are runtime. You should probably test if require was successful as a result.
e.g.:
if ( $somecondition ) {
eval { require Some::Module };
warn "Module Not loaded: ".$# if $#;
}
Otherwise you may be looking for:
Is it possible to pass parameters to a Perl module loading?
#!/usr/bin/perl
package MyObject;
sub import {
my ( $package, $msg ) = #_;
if ( defined $msg and $msg eq "NO_USE" ) {
#don't load module
}
else {
require XML::Twig;
}
}
1;
And then call:
use if $somecondition, MyObject => ( 'NO_USE' );
Or just simpler:
use MyObject qw( NO_USE );
Edit:
After a bit of fiddling with 'use' - there's a couple of gotchas, in that use if doesn't seem to like lexical variables. So you need to do something like:
#!/usr/bin/perl
package MyObject;
use strict;
use warnings;
our $import_stuff = 1;
sub import {
my ( $package, $msg ) = #_;
if ( $msg and $msg eq "NO_USE" ) {
$import_stuff = 0;
}
use if $import_stuff, 'Text::CSV';
}
1;
And call:
#!/usr/bin/perl
use strict;
use warnings;
use MyObject qw( NO_USE );
use Data::Dumper;
print Dumper \%INC;
my $test = Text::CSV -> new();
(Which errors if you set NO_USE and doesn't otherwise).
I think that's an artifact of use being a compile time directive still, so requires a (package scoped) condition.

Perl prototype subroutine in class

I am trying to call a prototype function from a class without instantiating an object. An example of my class MyClass :
package MyClass;
use strict;
use warnings;
sub import{
my $class = shift;
my ($caller) = caller();
eval "sub ${caller}::myprot(\&);";
eval "*${caller}::myprot = \&MyClass::myprot;";
}
sub myprot (&) {
my ($f) = #_;
$f->();
}
1;
I want to call the prototype from a script main.pl:
use strict;
use warnings;
use MyClass;
myprot {
print "myprot\n";
};
and I am getting the errors:
Use of uninitialized value in subroutine entry at MyClass.pm line 14.
Use of uninitialized value in subroutine entry at MyClass.pm line 14.
Undefined subroutine &main::myprot called at main.pm line 8.
I don't really understand the undefined subroutine error: With use, import is called which defines the prototype for main.pl. I also really don't understand the uninitialised value error.
I'd be happy for some explanation.
You're looking for Exporter.
package MyClass;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT = qw( myprot );
sub myprot(&) {
my ($f) = #_;
$f->();
}
1;
I usually use #EXPORT_OK (requiring the use of use MyClass qw( myprot );) rather than exporting by default.
There's a bunch of sketchy things going on in that code.
Unchecked use of eval means if it fails, you'll never know. eval should be used as eval "code" or die $#. You'll find it's throwing an error because strict does not like it when you mess with the symbol table (that's what *name = \&code is doing).
Using eval to export subroutines is overkill. eval STRING is a potential security hole and should be used as a last resort (eval BLOCK is fine). You can manipulate the symbol table without eval, but strict will not like the use of symbolic references.
my $caller = "foo";
*{"${caller}::myprot"} = \&MyClass::myprot;
# Can't use string ("foo::myprot") as a symbol ref while "strict refs" in use...
You have to turn off strict first. This is generally known as "aliasing".
no strict 'refs';
*{$caller.'::myprot'} = \&myprot;
Setting the prototype beforehand is unnecessary, the alias will take care of it for you.
It turns out this is all unnecessary, there's a number of modules which do this for you. The most common one is Exporter and comes with Perl. This makes your custom import unnecessary.
use Exporter 'import';
our #EXPORT = qw(myprot);
Other general tips...
Hard coding the name of a class in a class (ie. \&MyClass::myprot should just be \&myprot) should be avoided. It makes it harder to change the class or move the code around.
Hybrid modules which are both classes and export functions, are discouraged. They're harder to use, test and document and produce odd side effects. You should put myprot into its own module.
Are you sure you really want to do this?
The problem is that the double quotes will eat the backslash you have in the glob assignment.
eval "*${caller}::myprot = \&MyClass::myprot;"
should be
eval "*${caller}::myprot = \\&MyClass::myprot;"
But please don't ask me to debug your code!

using variables of one perl file in another

I am writing two perl script which requires an array consisting long list of strings
Here I wanted to declare my array in a separate perl package and use this package to access that array in other two perl scripts
Can you please tell me how could i do this
I checked for perl cpan module Exporter, but could find it can export subroutines,I only want my array to be exported not any subroutines
Thank you in advance.
Exporter can handle any package symbol, be it a subroutine or variable:
package My::Package;
use parent 'Exporter';
our #EXPORT_OK = qw/#foo/;
our #foo = (42, 666);
Then:
use My::Package qw/#foo/;
print "#foo\n";
Output: 42 666.
However, package variables (aka. “globals”) are frowned upon. Usually, techniques like object orientation provide a better solution. If you don't want to go there, you could still write a kind of “accessor” or “initializer”:
package My::Package;
sub main {
my #foo = (42, 666);
return \#foo;
}
Then:
use My::Package;
my $foo = My::Package::main();
print "#$foo\n";
You can create a package variable and export it, just like a subroutine:
package Local::Foo;
use strict;
use warnings;
use Exporter qw(import); # Allows you to export things
our #EXPORT = qw(#foo_array);
our #foo_array = ( ... );
1;
Now, you can use it in your program:
my #local_array = #foo_array;
This is called a really. really bad idea. Variables are polluting your main program's namespace without your knowledge. Plus, you could change #foo_array and destroy its special meaning.
If you go this route, do not do the export. Simply refer to the variable directly via the package name. After all, you've declared it with our:
package Local::Foo;
...
our #foo_array = ( ... );
And, in your program:
my #program_array = #Local::Foo::foo_array;
This is a tiny bit better. You won't have namespace collisions, and you know where that value is coming from. However, I would take the lead of use constant which uses subroutines to define constants. When you say this:
use PI => 3.141529;
What you're really doing is this:
sub PI {
return 3.141529;
}
That allows you to do this:
my $circumference = PI * ( 2 * $radius );
You could take a similar task with your array:
package Local::Foo;
use strict;
use warnings;
use Exporter qw(import);
our #EXPORT_OK = qw(foo_array);
sub foo_array {
return qw( ... );
}
Now, to use this in your program:
use Local::Foo qw(foo_array);
...
my #program_array - foo_array;
You can access the value of foo_array, but you can't change it at all. It's totally protected -- a constant value.
Yeah, I have to echo amon's deprecation of exporting. You can create it as a constant
package TheData;
use constant BIG_ARRAY => [ 0..300_000 ];
And then other packages can reference it as if it were a static member:
package DataUser;
my $big_array_data = TheData->BIG_ARRAY;
Much cleaner for a more modern Perl. (Note that constant just is shorthand for what amon specified.)

How do I use constants from a Perl module?

If I define a constant in a Perl module, how do I use that constant in my main program? (Or how do I call that constant in the main program?)
Constants can be exported just like other package symbols. Using the standard Exporter module, you can export constants from a package like this:
package Foo;
use strict;
use warnings;
use base 'Exporter';
use constant CONST => 42;
our #EXPORT_OK = ('CONST');
1;
Then, in a client script (or other module)
use Foo 'CONST';
print CONST;
You can use the %EXPORT_TAGS hash (see the Exporter documentation) to define groups of constants that can be exported with a single import argument.
Update: Here's an example of how to use the %EXPORT_TAGS feature if you have multiple constants.
use constant LARRY => 42;
use constant CURLY => 43;
use constant MOE => 44;
our #EXPORT_OK = ('LARRY', 'CURLY', 'MOE');
our %EXPORT_TAGS = ( stooges => [ 'LARRY', 'CURLY', 'MOE' ] );
Then you can say
use Foo ':stooges';
print "$_\n" for LARRY, CURLY, MOE;
Constants are just subs with empty prototype, so they can be exported like any other sub.
# file Foo.pm
package Foo;
use constant BAR => 123;
use Exporter qw(import);
our #EXPORT_OK = qw(BAR);
# file main.pl:
use Foo qw(BAR);
print BAR;
To expand on the earlier answers, since constants are really just subs, you can also call them directly:
use Foo;
print Foo::BAR;
You might want to consider using Readonly instead of constant.
package Foo;
use Readonly;
Readonly my $C1 => 'const1';
Readonly our $C2 => 'const2';
sub get_c1 { return $C1 }
1;
perl -MFoo -e 'print "$_\n" for Foo->get_c1, $Foo::C2'
To add to the bag of tricks, since a constant is just a subroutine you can even call it as a class method.
package Foo;
use constant PI => 3.14;
print Foo->PI;
If you have lots of constants it's a nice way to get at the occasional one without having to export them all. However, unlike Foo::PI or exporting PI, Perl will not compile out Foo->PI so you incur the cost of a method call (which probably doesn't matter).