Undefined subroutine &main::add called at ex1.pl line 4 - perl

I have a perl Module
MyMathLib.pm
package MyMathLib;
require Exporter;
#ISA = qw/EXPORTER/;
#EXPORT = qw/add/;
sub add
{
$_[0] + $_[1];
}
1;
Ex1.pl
#!usr/bin/perl
#
use MyMathLib;
print add(1,2);
I am getting the below error:
Undefined subroutine &main::add called at ex1.pl line 4.
What could be the reason?

It's an Exporter not an EXPORTER.
If you include
use strict;
use warnings;
in your scripts you'll activate more checks that would have shown you a clue to the problem:
Can't locate package EXPORTER for #MyMathLib::ISA at Ex1.pl line 5.
Undefined subroutine &main::add called at Ex1.pl line 6.

Related

How to import subroutines from modules in perl

I am novice in perl. I have this sample code.
#! /usr/bin/perl
# Calcu.pm
package Calc;
sub add {
( $one , $two ) = #_;
$total = $one + $two;
return $total;
}
1;
&
#! /usr/bin/perl
# add.pl
use Calcu;
print Calcu::add(50, 60);
script add.pl is running fine. but I want to call the add method without mentioning its module name. I googled & added below lines in my Calcu.pm
use Exporter;
#ISA = (Exporter);
#EXPORT = qw (add);
& replace print Calcu::add(50, 60); with print add(50, 60); in add.pl but it is still giving me the below error.
Undefined subroutine &main::add called at add.pl
Is there any way possible so that I can directly call add subroutine in my ad.pl?
Change package Calc; to package Calcu; in Calcu.pm
The mismatch in package names is what is giving you trouble.
Have a read through perldoc Exporter for the gory details.
Have a look at perldoc perlootut for an overview of different ways in perl to create objects.

Compilation error depends on 'use' order

I have these three files
Constants/Requests.pm
#!/usr/bin/perl
use strict;
use base 'Exporter';
use constant MR_NOACTION => 0;
use constant MR_START => 1;
use constant MR_STOP => 2;
our #EXPORT = (
'MR_NOACTION',
'MR_START',
'MR_STOP'
);
1;
JobManDB.pm
#!/usr/bin/perl
package JobManDB;
use strict;
use warnings;
use constant WEB_DB_FILE => "db/web.db";
use constant MASTER_DB_FILE => "db/master.db";
use Constants::Requests;
sub new
{
print "Ahoj: " . MR_NOACTION . "\n";
...
Master.pm
#!/usr/bin/perl
package Master;
use strict;
use warnings;
use Time::HiRes qw( usleep );
use Data::Dumper;
use JobManDB; # use #1
use Constants::Requests; # use #2
...
Program as posted is working, if but if I swith use #1 with use #2 the compilation fails with error:
Bareword "MR_NOACTION" not allowed while "strict subs" in use at lib/JobManDB.pm line 26.
(line 26 is the line in 'new' subroutine). I would like to know why. Thank you.
EDIT:
Another issue is, that if I add line package Requests; at the beginning of Requests.pm, the compilation fails with the same error but independently on order of 'uses'.
The Requests.pm file is missing its package declaration, package Constants::Requests;.

Importing a .pl file

I was wondering how to import a Perl file to a script. I experimented with use, require and do, but nothing seems to work for me. This is how I did it with require:
#!/usr/bin/perl
require {
(equations)
}
print "$x1\n";
Is it possible to code for substituting a value (I get in my script) into equations.pl, then have my script use an equation defined in equations.pl to calculate another value? How do I do this?
You can require a .pl file, which will then execute the code in it, but in order to access variables, you need a package, and either "use" instead of require (the easy way) or via Exporter.
http://perldoc.perl.org/perlmod.html
Simple example: here's the stuff you want to import, name it Example.pm:
package Example;
our $X = 666;
1; # packages need to return true.
And here's how to use it:
#!/usr/bin/perl -w
use strict;
use Example;
print $Example::X;
This presumes Example.pm is in the same directory, or the top level of an #INC directory.
equations.pm file:
package equations;
sub add_numbers {
my #num = #_;
my $total = 0;
$total += $_ for #num;
$total;
}
1;
test.pl file:
#!/usr/bin/perl -w
use strict;
use equations;
print equations::add_numbers(1, 2), "\n";
output:
3
You can't import a file. You can execute a file and import symbols (variables and subs) from it. See Perl Modules in perlmod.
You've given very few details about equations.pl, but if the input can be given via a command line argument, then you can open a pipe:
use strict;
use warnings;
my $variable; #the variable that you will get from equations.pl
my $input=5; #the input into equations.pl
open (my $fh,"-|","perl equations.pl $input") or die $!;
while(my $output=<$fh>)
{
chomp($output); #remove trailing newline
$variable=$output;
}
if(defined($variable))
{
print "It worked! \$variable=$variable\n";
}
else
{
print "Nope, \$variable is still undefined...\n";
}
If this is the body of equations.pl:
use strict;
use warnings;
my $foo=$ARGV[0];
$foo++;
print "$foo\n";
Then the code above outputs:
It worked! $variable=6

How can I call a subroutine whose name is a value in a hash, in Perl?

$ cat test.pl
use strict;
use warnings;
sub route {
print "hello, world!";
}
my %h;
$h{'a'} = 'route';
print "1\n";
$h{a};
print "2\n";
$h{a}();
print "3\n";
"$h{a}".();
$ perl test.pl
Useless use of hash element in void context at test.pl line 12.
Useless use of concatenation (.) or string in void context at test.pl line 18.
1
2
Can't use string ("route") as a subroutine ref while "strict refs" in use at test.pl line 15.
$
What is the right way to call route()?
You're trying to use $h{a} as a symbol reference. And that's explicitly disallowed by "use strict". If you turn off strict mode, then you can do it like this:
no strict;
&{$h{a}};
But the best approach is to store a "real" reference to the subroutine in your hash.
#!/usr/bin/perl
use strict;
use warnings;
sub route {
print "hello, world!";
}
my %h;
$h{a} = \&route;
$h{a}->();
You have to dereference the string containing the routine name as a sub. The parenthesis are optional.
my $name = 'route';
&{$name};
As your routine name is a hash value, you have to extract it from the hash. Also as you are using strict (which is a good practice), you have to locally disable checks.
{
no strict 'refs';
&{$h{a}};
}
However, as davorg suggested in his answer, it would be better (performance-wise) to directly store a reference to the sub in your hash, instead of the routine name.

Why don't I get the right package variable when using our()?

The below program prints "var = 13" and "var = 13". Shouldn't it print "var = 3" and "var = 13"?
use warnings;
use strict;
package p1;
our $var = 3;
package p2;
our $var = 13;
sub temp
{
package p2;
print "var = $var\n";
}
package p1;
print "var = $var\n"; #This prints var = 13. Why is it picking p2::var as the current package is p1?
&p2::temp;
From the first paragraph of perldoc -f our:
our associates a simple name with a package variable in the current package for use within the current scope. When use strict 'vars' is in effect, our lets you use declared global
variables without qualifying them with package names, within the lexical scope of the our declaration. In this way our differs from use vars , which is package scoped.
Your first our creates an alias of $p1::var named $var in the current scope. That scope runs until the end of the file (package statements do not create a new scope). But then you create a new alias to $var ($p2::var). So that alias lasts until the end of the scope (i.e. the file) or the next redefinition of the alias.
If you want to limit the scope of our, create a new scope:
#!/use/bin/perl
package p1;
use strict;
use warnings;
our $var = 3;
{
package p2;
use strict;
use warnings;
our $var = 13;
}
print "$var in package ", __PACKAGE__, "\n";
{
package p2;
use strict;
use warnings;
our $var;
print "$var in package ", __PACKAGE__, "\n";
}
print "$var in package ", __PACKAGE__, "\n";