Perl Importing Variables From Calling Module - perl

I have a Perl module (Module.pm) that initializes a number of variables, some of which I'd like to import ($VAR2, $VAR3) into additional submodules that it might load during execution.
The way I'm currently setting up Module.pm is as follows:
package Module;
use warnings;
use strict;
use vars qw($SUBMODULES $VAR1 $VAR2 $VAR3);
require Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw($VAR2 $VAR3);
sub new {
my ($package) = #_;
my $self = {};
bless ($self, $package);
return $self;
}
sub SubModules1 {
my $self = shift;
if($SUBMODULES->{'1'}) { return $SUBMODULES->{'1'}; }
# Load & cache submodule
require Module::SubModule1;
$SUBMODULES->{'1'} = Module::SubModule1->new(#_);
return $SUBMODULES->{'1'};
}
sub SubModules2 {
my $self = shift;
if($SUBMODULES->{'2'}) { return $SUBMODULES->{'2'}; }
# Load & cache submodule
require Module::SubModule2;
$SUBMODULES->{'2'} = Module::SubModule2->new(#_);
return $SUBMODULES->{'2'};
}
Each submodule is structured as follows:
package Module::SubModule1;
use warnings;
use strict;
use Carp;
use vars qw();
sub new {
my ($package) = #_;
my $self = {};
bless ($self, $package);
return $self;
}
I want to be able to import the $VAR2 and $VAR3 variables into each of the submodules without having to reference them as $Module::VAR2 and $Module::VAR3. I noticed that the calling script is able to access both the variables that I have exported in Module.pm in the desired fashion but SubModule1.pm and SubModule2.pm still have to reference the variables as being from Module.pm.
I tried updating each submodule as follows which unfortunately didn't work I was hoping:
package Module::SubModule1;
use warnings;
use strict;
use Carp;
use vars qw($VAR2 $VAR3);
sub new {
my ($package) = #_;
my $self = {};
bless ($self, $package);
$VAR2 = $Module::VAR2;
$VAR3 = $Module::VAR3;
return $self;
}
Please let me know how I can successfully export $VAR2 and $VAR3 from Module.pm into each Submodule. Thanks in advance for your help!

In your submodules, are you forgetting to say
use Module;
? Calling use Module from another package (say Module::Submodule9) will try to run the Module::import method. Since you don't have that method, it will call the Exporter::import method, and that is where the magic that exports Module's variables into the Module::Submodule9 namespace will happen.
In your program there is only one Module namespace and only one instance of the (global) variable $Module::VAR2. Exporting creates aliases to this variable in other namespaces, so the same variable can be accessed in different ways. Try this in a separate script:
package Whatever;
use Module;
use strict;
use vars qw($VAR2);
$Module::VAR2 = 5;
print $Whatever::VAR2; # should be 5.
$VAR2 = 14; # same as $Whatever::VAR2 = 14
print $Module::VAR2; # should be 14

Well there is the easy way:
In M.pm:
package M;
use strict;
use warnings;
#our is better than "use vars" for creating package variables
#it creates an alias to $M::foo named $foo in the current lexical scope
our $foo = 5;
sub inM { print "$foo\n" }
1;
In M/S.pm
package M;
#creates an alias to $M::foo that will last for the entire scope,
#in this case the entire file
our $foo;
package M::S;
use strict;
use warnings;
sub inMS { print "$foo\n" }
1;
In the script:
#!/usr/bin/perl
use strict;
use warnings;
use M;
use M::S;
M::inM();
M::S::inMS();
But I would advise against this. Global variables are not a good practice, and sharing global variables between modules is even worse.

Related

Perl: How to make sure overridden method is called when accessed from within the base class

I have a base class which calls a method which is overridden in a child class, in Perl. Currently, it still calls the base class version of the method, but I want it to call the base if there is one. Here is a simplified rendition of my code:
package Test;
use strict;
use warnings;
sub Main
{
my $self = shift;
return $self->SomeFunc();
}
sub SomeFunc
{
my $self = shift;
#...
return 1;
}
package Test2;
use strict;
use warnings;
use base qw(Test);
sub SomeFunc
{
my $self = shift;
#...
return 0;
}
package main;
use Test2;
my $test = new Test2();
print $test->Main();
and I am getting a 1 when I run this!
PS my apologies, I'm not used to creating examples in working perl code, please forgive the obvious errors.
The problem would be in your constructor, but you don't have one so your code doesn't even do what you say it does
You have probably written something like
sub new {
bless {};
}
which blesses an empty hash into the current package. Instead you need to take the class name from the first parameter passed to the constructor, like this
You should also avoid using capital letters in your lexical identifiers as they are reserved for global identifiers like package names. If you must use CamelCase then at least makeSureTheFirstLetterIsLowerCase. The standard for both Perl and Python is to use the much_clearer_snake_case
Test.pm
package Test;
use strict;
use warnings;
sub new {
my $class = shift;
bless {}, $class;
}
sub main {
my $self = shift;
$self->some_func();
}
sub some_func {
my $self = shift;
'Test::some_func';
}
Test2.pm
package Test2;
use strict;
use warnings;
use parent 'Test';
sub some_func {
my $self = shift;
'Test2::some_func';
}
main.pl
use strict;
use warnings;
my $test = Test->new;
print $test->main, "\n";
$test = Test2->new;
print $test->main, "\n";
output
Test::some_func
Test2::some_func
new doesn't mean anything in perl unless you make a function with that method name.
You need to bless an object
You can either directly bless an object
my $test = { };
bless $test, "Test2";
or make a new method that does the blessing for you:
sub new{
my $class = shift;
my $test = { };
bless $test, $class;
}

Perl: Best way of making parent subroutine (not method) available to children

I have multiple classes defined in my main program. One is a parent class. The other are children classes:
# Main Program
...
package Foo; #Parent class
....
sub glob2regex {
my $glob = shift;
...here be dragons...
return $regex;
};
....
package Foo::Bar; #Child Class
base qw(Foo);
sub some_method {
my $self = shift;
my $regex = shift;
my $type = shift;
if ( $type eq "glob" ) {
$regex = glob2regex($regex); #ERROR: glob2regex is not defined.
}
...
}
I have a function in my parent class called glob2regex. It isn't really a method because it doesn't do anything with the object. Instead, it's a helper function that my child classes can use.
However, calling it in my child class as shown above won't work because it's not defined in my child class. I could prepend the full parent class name on it (i.e. call it as Foo::glob2regex instead of just glob2regex), or I could modify it into an object, and call it as $self->glob2regex. There maybe a even better way of handling this situation that I'm overlooking.
What is the best way to make a function like this that's defined in the parent class available in the child classes?
--
Test Program
#! /usr/bin/env perl
#
use strict;
use warnings;
use feature qw(say);
use utf8;
########################################################################
# MAIN PROGRAM
my $bar = Foo::Bar->new;
$bar->just_foo_it;
#
########################################################################
########################################################################
#
package Foo;
sub lets_foo_it {
say "I've done foo!";
}
#
########################################################################
########################################################################
#
package Foo::Bar;
use base qw(Foo);
*Foo::Bar::lets_foo_it = *Foo::lets_foo_it;
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
sub just_foo_it {
my $self = shift;
lets_foo_it();
}
#
########################################################################
Exporting is usually done using Exporter.
BEGIN {
package Foo;
use Exporter qw( import );
our #EXPORT_OK = qw( glob2regex );
sub glob2regex { ... }
...
$INC{'Foo.pm'} = 1;
}
BEGIN {
package Foo::Bar;
use Foo qw( glob2regex );
our #ISA = 'Foo';
... glob2regex(...) ...
$INC{'Foo/Bar.pm'} = 1;
}
Note that it's very unusual for a class module to export subroutines. You should consider it a red flag indicating a likely design flaw.
Seems like a bit of your problem is: "How do I use within a file?". I have a pragma I use in early development for this type of thing, but it breaks down to:
package Foo;
BEGIN { $INC{ __PACKAGE__ . '.pm'} = __FILE__ . ':' . ( __LINE__ - 1 ); }
Once it's in the %INC table, you're usually fine just using it.
Remember that a use is a require combined with an import at compile time. Once you've defined the Foo import, you can create an import function to take care of that part of use.
sub import {
my $caller = caller;
return unless $caller->isa( __PACKAGE__ );
{ no strict 'refs';
*{"$caller\::glob2regex"} = *glob2regex{CODE};
}
}
As I wrote above, I use this type of thing in early development--basically, when I want a sort of "scratchpad" with object relationships. In maintainable code, my preference would be to call Foo::glob2regex(...), or as I have at times insert it into a util package and export it from there:
package Foo::Util;
use strict;
use warnings;
use parent 'Exporter';
our #EXPORT_OK = qw<glob2regex>;
sub glob2regex { ... }

How do I read args passed to the constructor and args passed by `use Module` in Perl?

Currently I am making a new module and I was wondering how could I implement in my module 2 things.
We often see the use like:
use My::Module qw(something);
for example:
use CGI::Carp qw(fatalsToBrowser);
So the first question is, how do i
retrieve this, i mean wether the
user has specified anything and what
he specified ?
Second question is, How do i pass and read the args
directly on the constructor like
this:
my $my_module = My::Module->new(arg1,arg2,arg3);
AS requested on the comment the simple module test code:
package My::Module;
# $Id$
use strict;
use Carp;
sub new {
my $class = shift;
my $self = {};
$self->{ARG1} = undef;
$self->{ARG2} = undef;
$self->{ARG3} = undef;
$self->{ARG4} = undef;
bless($self,$class);
return $self;
}
sub arg1 {
my $self = shift;
if (#_) { $self->{ARG1} = shift }
return $self->{ARG1};
}
sub arg2 {
my $self = shift;
if (#_) { $self->{ARG2} = shift }
return $self->{ARG2};
}
sub arg3 {
my $self = shift;
if (#_) { $self->{ARG3} = shift }
return $self->{ARG3};
}
sub arg4 {
my $self = shift;
if (#_) { $self->{ARG4} = shift }
return $self->{ARG4};
}
sub dump {
my $self = shift;
require Data::Dumper;
my $d = Data::Dumper->new([$self], [ref $self]);
$d->Deepcopy(1);
return $d->Dump();
}
1; # so the require or use succeeds
perldoc -f use explains that the use keyword is simply loading a module during compile-time, and then calling ->import on it. The arguments a caller gave to the use statement will be passed to the import method call.
As for your second question: constructors are just methods. Getting their arguments works like it does for any other method or function, using the #_ variable.
import subroutine gets the arguments passed in a use. The following code samples should help you.
File: My/Module.pm
package My::Module;
use warnings;
use strict;
use Data::Dumper;
sub import {
my ( $package, #args ) = #_;
print Dumper \#args;
}
1;
File: module.pl
#!/usr/bin/env perl
use warnings;
use strict;
use My::Module qw(something);
If you are programming an object oriented module, you may try Moose which will save you lots of time.

How does the Perl 'use' syntax work?

Sample code:
m1.pm
my $a;
my $b;
sub init {
$a = shift;
$b = shift;
}
sub printab {
print "a = -$a-\n";
print "b = -$b-\n";
}
1;
m2.pm
my $a;
my $b;
sub init {
$a = shift;
$b = shift;
}
1;
test.pl
use strict;
use warnings;
use m1;
use m2;
init('hello', 'world');
printab();
Run:
$ perl test.pl
a = --
b = --
$
What happens is that the init('hello', 'world') call is mapped to m2.pm and initializes the variables ($a and $b) there.
This kind of makes sense, but what I do not understand is why those values are not available in test.pl.
Is there something fundamentally wrong that I am trying to do here? What is the correct way to use two modules with same named subroutines and variables?
How exactly does a Perl use work? It would help if someone could contrast it with C's #include directive.
In Perl, the use keyword is exactly equivalent to the following:
use Mymodule;
#is the same as
BEGIN {
require Mymodule;
Mymodule->import();
}
So if you are not defining an import routine in your code (or inheriting from Exporter), then your modules are not importing anything into test.pl
As Sinan caught, you are not declaring a package in your modules, so they are defaulting to the main package. In that case, all of your subroutines are in main, but the lexical variables (declared with my) are only scoped to the file they are declared in.
So m1 defines sub init and sub printab to which the lexicals $a and $b are in scope. But then when test.pl loads m2, the init routine is overwritten with the new definition, which is not closed around the two lexicals anymore. So it is writing to the package variables $main::a and $main::b instead of the lexicals which printab is bound to.
If you had warnings enabled (which you always should when learning), you would have been warned about the subroutine redefinition.
You should start each of your modules with:
package Some::Package::Name;
use warnings;
use strict;
and then end each module with:
1;
This is because when you use/require a module, it needs to return a true value at the end so that Perl knows it loaded properly.
First, do read perldoc perlmod.
You do not declare a namespace in either module, so everything is in the main namespace. Declare package m1; in m1.pm and package m2; in m2.pm.
At the very least, you should implement an import method (or inherit the one Exporter provides) so that programs that use modules can decide what to import from where.
It also seems to me that you are exploring around the edges of OO.
Further:
Avoid using $a and $b as variable names because it is easy to confuse them with the package variables $a and $b used by sort.
Don't use lower case module names: They are reserved for pragmata.
A minimal implementation (all in one file for testing convenience) looks like this:
package My::M1;
use strict; use warnings;
sub new { my $class = shift; bless { #_ } => $class }
sub a {
my $self = shift;
my ($v) = #_;
$self->{a} = $v if #_;
return $self->{a};
}
sub b {
my $self = shift;
my ($v) = #_;
$self->{b} = $v if #_;
return $self->{b};
}
package My::M2;
use strict; use warnings;
use base 'My::M1';
sub printtab {
my $self = shift;
for my $x (qw(a b)) {
printf "%s = -%s-\n", $x, $self->$x;
}
}
package main;
my $m = My::M2->new(a => 'hello', 'b' => 'world');
$m->printtab;
printab() is defined in the file m1.pm and only has access to the $a and $b variables that are scoped to that file. The variables $a and $b in m2.pm are scoped to that file, and they are different variables than the $a and $b in m1.pm.
init() sets the variables scoped in m2.pm (because that's the last place the &init function was defined) so it is not setting the same variables that printab() will be trying to print.

How do I inherit subroutines in Perl with 'use base'?

How do I apply 'use base' in Perl to inherit subs from some base module?
I'm used to C++ inheritance mechanics, and all the sites I googled for this caused more confusion then help. I want to do something like the following:
#! /usr/bin/perl
#The base class to inherit from
use strict;
use warnings;
package 'TestBase';
#-------------------------------
sub tbSub
{
my ($self, $parm) = #_;
print "\nTestBase: $parm\n";
}
1;
.
#! /usr/bin/perl
#The descendent class
use strict;
use warnings;
use base qw(TestBase);
sub main;
sub mySub;
#-------------------------------
#Entry point...
main();
#---code------------------------
sub main
{
mySub(1);
tbSub(2);
mySub(3);
}
#-------------------------------
sub mySub
{
my $parm = shift;
print "\nTester: $parm\n";
}
Perl complains/cannot find tbSub.
The C++ mechnics aren't much different than the Perl mechanics: To use inheritance, you need two classes: the base class and the inheriting class. But you don't have any descendent class.
You are also lacking a constructor. Unlike C++, Perl will not provide a default constructor for you.
Your base class contains a bad syntax error, so I guess you didn't try the code before posting.
Finally, as tsee already observed, you will have to let Perl know whether you want a function call or a method call.
What you really want would look something like this:
my $foo = TestDescendent->new();
$foo->main();
package TestBase;
sub new {
my $class = shift;
return bless {}, $class;
}
sub tbSub
{
my ($self, $parm) = #_;
print "\nTestBase: $parm\n";
}
package TestDescendent;
use base 'TestBase';
sub main {
my $self = shift;
$self->mySub( 1 );
$self->tbSub( 2 );
$self->mySub( 3 );
}
sub mySub
{
my $self = shift;
my $parm = shift;
print "\nTester: $parm\n";
}
1;
You should have a look at using Moose which is a postmodern object system for Perl5. You will probably find it a lot easier to grasp than using standard Perl OO semantics... especially when coming from another OO language.
Here's a Moose version of your question....
package TestBase;
use Moose;
sub tbSub {
my ($self, $parm) = #_;
print "\nTestBase: $parm\n";
}
package TestDescendent;
use Moose;
extends 'TestBase';
sub main {
my $self = shift;
$self->mySub( 1 );
$self->tbSub( 2 );
$self->mySub( 3 );
}
sub mySub {
my ($self, $parm) = #_;
print "\nTester: $parm\n";
}
package main;
my $foo = TestDescendent->new();
$foo->main
The differences are....
Constructor automatically created for you &
Inheritance defined by "extends" command instead of "use base".
So this example only covers the tip of the Moose iceberg ;-)
As a sidenote, there is little good reason to use base rather than the newer use parent.
It seems to me, you are mixing up two things here: Object-Oriented and Procedural Perl. Perl OO is kind of "different" (as in not mainstream but workable).
Your TestBase.pm module seems to expect to be run as a Perl object (Perl oo-style), but your Perl script wants to access it as "normal" module. Perl doesn't work the way C++ does (as you realised) so you would have to construct your code differently. See Damian Conway's books for explanations (and smarter code than mine below).
Procedural:
#! /usr/bin/perl
#The module to inherit from
package TestBase;
use strict;
use warnings;
use Exporter ();
our #ISA = qw (Exporter);
our #EXPORT = qw (tbSub);
#-------------------------------
sub tbSub
{
my ($parm) = #_;
print "\nTestBase: $parm\n";
}
1;
.
#! /usr/bin/perl
#The descendent class
use strict;
use warnings;
use TestBase;
sub main;
sub mySub;
#-------------------------------
#Entry point...
main();
#---code------------------------
sub main
{
mySub(1);
tbSub(2);
mySub(3);
}
#-------------------------------
sub mySub
{
my $parm = shift;
print "\nTester: $parm\n";
}
Perl OO
#! /usr/bin/perl
#The base class to inherit from
package TestBase;
use strict;
use warnings;
#-------------------------------
sub new { my $s={ };
return bless $s;
}
sub tbSub
{
my ($self,$parm) = #_;
print "\nTestBase: $parm\n";
}
1;
.
#! /usr/bin/perl
#The descendent class
use strict;
use warnings;
use TestBase;
sub main;
sub mySub;
#-------------------------------
#Entry point...
main();
#---code------------------------
sub main
{
my $tb = TestBase->new();
mySub(1);
$tb->tbSub(2);
mySub(3);
}
#-------------------------------
sub mySub
{
my $parm = shift;
print "\nTester: $parm\n";
}
Perl's inheritance inherits methods, not functions. That means you will have to call
main->tbSub(2);
However, what you really want is to inherit the method into a proper class:
package Derived;
use base "TestBase";
package main;
Derived->somemethod("foo");
Calling methods in the current package as functions won't pass in the $self or "this" object nor the class name magically. Internally,
Class->somemethod("foo")
essentially ends up being called as
Class::somemethod("Class", "foo")
internally. Of course, this assumes Class has a subroutine/method named "somemethod". If not, the superclasses of Class will be checked and if those don't have a method "somemethod" either, you'll get a fatal error. (Same logic applies for $obj->method("foo").)
OO syntax uses the -> operator to separate the message and arguments from the receiver of the message. A short illustration below.
You->do_something( #params );
OR
$you->do_something( #params );
package A;
sub do_neat_thing {
my ( $class_or_instance, #args ) = #_;
my $class = ref( $class_or_instance );
if ( $class ) {
say "Instance of '$class' does a neat thing.";
}
else {
say "$class_or_instance does a neat thing.";
}
}
...
package main;
A->do_neat_thing(); # A does a neat thing.
my $a_obj = A->new();
$a_obj->do_neat_thing(); # Instance of 'A' does a neat thing.