How do I use constants from a Perl module? - perl

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

Related

perl use vs require and import, constants are only functions

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.

How to declare an array variable to be global in module scope

I have some code I decided to pull into a module in perl. I admit that I am doing a bit of monkey-see monkey-do stuff following documentation I've found online.
There is only one pubicly visible subroutine, which sets 2 variables * would like to use in other subroutines in the module, without passing them explicitly as parameters -- $fname, and #lines. Looking online I came up with the "our" keyword, but when I try to declare them at global level (see code snippet below), I get the following error:
mig_tools.pm did not return a true value at
I have worked around the issue by declaring "our $fname" and "our #lines" in every subroutine they are used, but I would prefer to declare them once at global scope. Is that possible?
Here's what I take to be the relevant part of the code.
package mig_tools;
require Exporter;
use strict;
use warnings;
our #ISA = qw(Exporter);
our #EXPORT = qw( ensure_included);
our $fname;
our #lines;
// definitions of already_has_include find_include_insert_point and ensure_included.
All-lowercase variables are reserved for local identifiers and pragma names. Your module should be in MigTools.pm and you should use it with use MigTools
The did not return a true value error is just because your module file didn't return a true value when it was executed. It is usual to add a line containing just 1; to the end of all modules
Your MigTools.pm should look like this. It is best to use the import directly from Exporter instead of subclassing it, and our doesn't help you to create a global variable, but I am a little worried about why you are structuring your module this way
package MigTools;
use strict;
use warnings;
use Exporter qw/ import /;
our #EXPORT = qw/ ensure_included /;
my ($fname, #lines)
sub ensure_included {
}
sub already_has_include {
}
sub find_include_insert_point {
}
sub ensure_included {
}
1;

Perl : Like in java we can access public member (variables) in other class is there any same concept in perl

I have 2 perl file and i want to use value of one variable in another perl file as input so how i can do it is there any concept like java we can declare it as public and use it.
any help appreciated thank you!
In this answer, I'll skip the discussion about whether it is the right decision to use OOP or not and just assume you want to do it the OOP-way.
In short, all variables of an object in Perl can be considered public. In fact, the problem is often the opposite - to make some of them private. Anyway, if you have a file Obj.pm which defines an object with a field foo which looks like this:
package Obj;
sub new {
my $class = shift;
my $self = {foo => "bar"};
bless $self, $class;
return $self;
}
you can access the foo variable as if it were public:
use Obj;
my $obj = Obj->new();
print $obj->{foo};
For perhaps a more pleasant OOP in Perl, look at the Moose package which gives you more flexibility.
As #user2864740 pointed you don't need "OO" in perl to share variables.It is one way, Let's say you have two files
Foo.pm(package):
#!/usr/bin/perl
use strict;
use warnings;
use Exporter;
package Foo;
our #ISA = qw(Exporter);
our #EXPORT = qw( blat); #exported by default
our #EXPORT_OK = qw(bar );#not exported by default
our $x="42";#variable to be shared should be "our" not "my"
sub bar {
print "Hello $_[0]\n"
}
sub blat {
print "World $_[0]\n"
}
1;
Access that variable from other file as
bar.pl :
#!/usr/bin/perl
use strict;
use warnings;
use Foo;
print "$Foo::x";#imported variable
blat("hello");#imported subroutine
If you want to import listed functions then:
#!/usr/bin/perl
use strict;
use warnings;
use Foo qw(bar blat);# import listed subs
print "$Foo::x";#imported variable
blat("hello ");#imported subroutine
bar("hi");#this also get imported

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

Why is constant not automatically inherited?

As we know constant in Perl is just sub,
but why are they not inherited?
As the matter of fact, they are:
use strict; use warnings;
package Father;
use constant CONST => 1;
package Child;
use base 'Father';
sub new { bless {}, shift }
package main;
my $c = Child->new;
print $c->CONST; # 1
print CONST(); # undefined subroutine
Methods are inherited, functions are not. If you want to inherit the constant, you'll need to call it like a method.
$self->FOO
or
__PACAKAGE__->FOO
That said, you should be importing constants, not inheriting them.