Properly Use this Perl Module - perl

I've looked at several examples of using a Perl module and I still can't get it right. I'm following this tutorial: http://www.perlmonks.org/?node_id=102347. For the following .pl and .pm files, I call
$ perl Solver.pl
and have the below error.
Undefined subroutine &main::mergeSort called at Solver.pl line 13.
Solver.pl
#!/usr/bin/perl
#Program usage: perl PROGRAM
#example:
#perl solver.pl
use strict;
use warnings;
use MergeSort qw(:DEFAULT);
### MAIN ###
mergeSort(\#list); #ERROR;
### END MAIN ###
MergeSort.pm
package MergeSort;
use strict;
use Exporter;
use vars qw($VERSION #ISA #EXPORT #EXPORT_OK %EXPORT_TAGS);
$VERSION = 1.00;
#ISA = qw(Exporter);
#EXPORT = ();
#EXPORT_OK = qw(mergeSort);
%EXPORT_TAGS = ( DEFAULT => [qw(&mergeSort)],
Both => [qw(&mergeSort &merge)]);
sub mergeSort{
...(defined here
}#end mergeSort()
sub merge{
...(defined here)
}#end merge()
1;

:DEFAULT has a builtin definition which takes precedence over yours. It exports all the symbols that are exported by default, which is to say all the symbols in #EXPORT. You should have used:
our #EXPORT = qw( mergeSort );
our #EXPORT_OK = #EXPORT;
our %EXPORT_TAGS = ( ALL => \#EXPORT_OK );
use MergeSort; # Same as: use MergeSort qw( :DEFAULT );
But I think explicitly listing one's imports is a good idea, so I'd use
our #EXPORT = qw( );
our #EXPORT_OK = qw( mergeSort );
our %EXPORT_TAGS = ( ALL => \#EXPORT_OK );
use MergeSort qw( mergeSort );

Related

Perl Module using %EXPORT_TAGS

I'm having trouble properly using %EXPORT_TAGS in my Perl module. In Solver.pl I have:
use MatrixFunctions qw(:Normal);
Then inside MatrixFunctions.pm, I have:
package MatrixFunctions;
use strict;
use Exporter;
use vars qw($VERSION #ISA #EXPORT #EXPORT_OK %EXPORT_TAGS);
$VERSION = 1.00;
#ISA = qw(Exporter);
#EXPORT = ();
#EXPORT_OK = qw(&det &identityMatrix &matrixAdd
&matrixScalarMultiply &matrixMultiplication);
%EXPORT_TAGS = ( Det => [qw(&det)],
Normal => [qw(&det &identityMatrix &matrixAdd
&matrixScalarMultiply &matrixMultiplication)]);
However it only works when I have #EXPORT_OK including all the methods. If I have
#EXPORT_OK = ();
I have the error:
"matrixScalarMultiply" is not exported by the MatrixFunctions module
"det" is not exported by the MatrixFunctions module
"matrixAdd" is not exported by the MatrixFunctions module
"matrixMultiplication" is not exported by the MatrixFunctions module
"identityMatrix" is not exported by the MatrixFunctions module
Can't continue after import errors at Solver.pl line 6.
BEGIN failed--compilation aborted at Solver.pl line 6.
The point of using qw(:Normal) in my Solver.pl file is so that I can have #EXPORT_OK empty I thought. What am I doing wrong?
perldoc -f Exporter under the Advanced Features section:
e.g., Module.pm defines:
#EXPORT = qw(A1 A2 A3 A4 A5);
#EXPORT_OK = qw(B1 B2 B3 B4 B5);
%EXPORT_TAGS = (T1 => [qw(A1 A2 B1 B2)], T2 => [qw(A1 A2 B3 B4)]);
Note that you cannot use tags in #EXPORT or #EXPORT_OK.
Names in EXPORT_TAGS must also appear in #EXPORT or #EXPORT_OK.
The bolded section above explains that you are required to have the functions you wish to place in %EXPORT_TAGS in either #EXPORT_OK or #EXPORT
A pattern that I have started using is to defined everything that I want to allow to be exported in #EXPORT_OK, then use #EXPORT_OK to build an `:all' tag:
our #ISA = qw(Exporter);
our #EXPORT_OK = qw/raspberry apple/;
our %EXPORT_TAGS = (
'all' => \#EXPORT_OK,
);
[Not an answer, but a follow-up to large for a comment]
If you want #EXPORT_OK automatically populated, you can use the following:
push #EXPORTER_OK, map #$_, values %EXPORT_TAGS;
Exporter doesn't care about duplicate entries. If you do, you can use the following instead:
my %EXPORT_OK;
#EXPORT_OK = grep !$EXPORT_OK{$_}++,
#EXPORT_OK, map #$_, values %EXPORT_TAGS;
So, after some cleaning up, your code would be the following:
package MatrixFunctions;
use strict;
use warnings;
use Exporter qw( import );
our $VERSION = 1.00;
our #EXPORT = ();
our #EXPORT_OK = ();
our %EXPORT_TAGS = (
Det => [qw( det )],
Normal => [qw( det identityMatrix matrixAdd matrixScalarMultiply matrixMultiplication )],
);
push #EXPORTER_OK, map #$_, values %EXPORT_TAGS;

How to use only the variable name from another file?

I want to use only the variable name from the another file.
test1.pl
use warnings;
use strict;
our $name = "hello world";
print "Helllloo\n";
test2.pl
use warnings;
use strict;
require "test.pl";
our $name;
print "$name\n";
test1.pl contain some content with many functions. I used the variable $name from the test1.pl. But Don't run test1.pl while running the test2.pl. For example when run the test2.pl it result was
Helllloo
hello world
That the Helllloo print from the test1.pl. How can use the another file variable name only How can i do it?
You should rewrite both test1.pl and test2.pl to use MyConfig, like this
test2.pl
use strict;
use warnings;
use MyConfig 'NAME';
print NAME, "\n";
MyConfig.pm
use strict;
use warnings;
package MyConfig;
use Exporter 'import';
our #EXPORT_OK = qw/ NAME /;
use constant NAME => "hello world";
1;
output
hello world
Use Const::Fast to export variables from a module:
use strict;
use warnings;
use My::Config '$NAME';
print "$NAME\n";
In My/Config.pm:
use strict;
use warnings;
package My::Config;
use Exporter 'import';
our #EXPORT = ();
our #EXPORT_OK = qw{ $NAME };
use Const::Fast;
const our $NAME => "hello world";
__PACKAGE__;
__END__

Attempt to use #INC and call function on demand

I am trying to learn how to use a .pm file. I created 2 files:
MyScript.pl
use strict;
BEGIN {
unshift(#INC,"./firstdir");
}
my #list = qw (J u s t ~ A n o t h e r ~ P e r l ~ H a c k e r !);
use seconddir::MyModule qw(func1) ;
print func1(#list),"\n"; #line 21
print MyModule::func2(#list),"\n";
MyModule.pm
package MyModule;
use strict;
use Exporter;
use vars qw($VERSION #ISA #EXPORT #EXPORT_OK %EXPORT_TAGS);
$VERSION = 1.00;
#ISA = qw(Exporter);
#EXPORT = ();
#EXPORT_OK = qw(func1 func2);
%EXPORT_TAGS = ( DEFAULT => [qw(&func1)],
Both => [qw(&func1 &func2)]);
sub func1 { return reverse #_ }
sub func2 { return map{ uc }#_ }
1;
the structure of the directories is as following:
--------------- ------------ ---------------
| firstdir ---|------> |seconddir--|-> | MyModule.pm |
| MyScript.pl | ------------ ---------------
---------------
note: firstdir and seconddir are directories
when I run the command Perl MyScript.pl I receive the following error:
Undefined subroutine &main::func1 called at MyScript.pl line 21
can you help me figure out what is wrong please?
Your package name is wrong, it should be:
package seconddir::MyModule
Then you should call func2 with:
print seconddir::MyModule::func2(#list),"\n";
or by exporting it, as with func1.
func1 should be in the #EXPORT array in the module MyModule.pm if you want to call it directly as func1 in your main script.
#EXPORT = qw(func1 func2);
You need to add the names of the symbols in the #EXPORT array in order to access them from you script.

access variables from different files in Perl

file1.pl
package ba;
#!/usr/bin/perl
use strict;
use warnings;
our $base_addr = 0x48;
file2.pl
package oa;
#!/usr/bin/perl
use strict;
use warnings;
our $offset_addr = 0;
file3.pl
#!/usr/bin/perl
do "file1.pl"
do "file2.pl"
my $final_val;
$final_val = $ba::base_addr + $oa::offset_addr;
printf "base_addr = 0x%0x\n", $ba::base_addr;
printf "offset_addr = 0x%0x\n", $oa::offset_addr;
printf "final addr = 0x%0x\n", $final_val;
ERRORS### ->
Argument "0x48" isn't numeric.
Use of uninitialized value.
Use of uninitialized value in addition.
Two major errors, both of which are found by using use strict; use warnings;. Always do so. (You used it in your modules, but not in your script.)
You correctly use $ba::base_addr in one spot, but then you proceeded to use non-existent variable $base_addr shortly afterwards.
You can only access $ba::base_addr as $base_addr if the current package is ba, or if you create an alias to it named $base_addr.
You either need to use $ba::base_addr consistently, or you need to export the variable to the using module. (This is one way to the alias I mentioned.)
You never assign a value to $ba::base_addr and $oa::offset_addr, so Perl gives you warnings when you attempt to add them ("not numeric") and when you try to print them ("uninitialized").
Some other problems we'll fix at the same time:
A module must return a true value, which is to say the last expression evaluated must evaluate to something true. It's thus standard to end a module with 1; (This applies to do too for reliable error detection: do $qfn or die $# || $!;.)
You should be using require instead of do since the files have a package declaration. It would be even better if you renamed them to .pm and used use.
The name of a module should match it's package declaration. If it contains package ba;, the file should be named ba.pm.
#! is only meaningful if 1) they are the first two characters of the file, and 2) if the file is provided to the OS for execution. Neither of those are the case for your modules.
ba.pm:
package ba;
use strict;
use warnings;
our $base_addr = 123;
1;
oa.pm:
package oa;
use strict;
use warnings;
our $offset_addr = 456;
1;
script.pl:
#!/usr/bin/perl
use strict;
use warnings;
use ba qw( );
use oa qw( );
my $final_val = $ba::base_addr + $oa::offset_addr;
print "base_addr = $ba::base_addr\n";
print "offset_addr = $oa::offset_addr\n";
print "final addr = $final_val\n";
You could avoid saying the package name everywhere if you exported the variables, and mentioned earlier.
ba.pm:
package ba;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT_OK = qw( $base_addr );
our $base_addr = 123;
1;
oa.pm:
package oa;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT_OK = qw( $offset_addr );
our $offset_addr = 456;
1;
script.pl:
#!/usr/bin/perl
use strict;
use warnings;
use ba qw( $base_addr );
use oa qw( $offset_addr );
my $final_val = $base_addr + $offset_addr;
print "base_addr = $base_addr\n";
print "offset_addr = $offset_addr\n";
print "final addr = $final_val\n";
It's typically bad form to export variables, though. It's usually far better to create accessors.
ba.pm:
package ba;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT_OK = qw( base_addr );
my $base_addr = 123;
sub base_addr { $base_addr }
1;
oa.pm:
package oa;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT_OK = qw( offset_addr );
my $offset_addr = 456;
sub base_addr { $base_addr }
1;
script.pl:
#!/usr/bin/perl
use strict;
use warnings;
use ba qw( base_addr );
use oa qw( offset_addr );
my $final_val = base_addr() + offset_addr();
print "base_addr = ".base_addr()."\n";
print "offset_addr = ".offset_addr()."\n";
print "final addr = $final_val\n";
You need to rename your files, add return values and include them using use. Here:
file1.pm
package ba;
use strict;
use warnings;
our $base_addr = 17;
1;
file2.pm
package oa;
use strict;
use warnings;
our $offset_addr = 19;
1;
file3.pl
#!/usr/bin/perl
use file1;
use file2;
my $final_val;
$final_val = $ba::base_addr + $oa::offset_addr;
print "base_addr = $ba::base_addr\n";
print "offset_addr = $oa::offset_addr\n";
print "final addr = $final_val\n";

Accessing value of a global variable using require?

Is it possible to access value of a global variable declared, in another perl script using require?
eg.
Config.pl
#!/usr/bin/perl
use warnings;
use strict;
our $test = "stackoverflow"
Main.pl
#!/usr/bin/perl
use warnings;
use stricts;
require "Config.pl"
print "$test\n";
print "$config::test\n";
sure. The way you have suggested almost works. Try:
Config.pl:
use warnings;
use strict;
our $test = "stackoverflow";
and the main program:
#!/usr/bin/perl
use warnings;
use strict;
require "Config.pl";
our $test;
print "$test\n";
When you call require, the file is executed in the same namespace as the caller. So without any namespaces or my declarations any variables assigned will be globals, and will be visible to the script.
You need to declare the variable $test in Main.pl by writing
our $test;
as you do in Config.pl. Then everything will work as you expect.
Better to use a module:
MyConfig.pm: (There's a core package called "Config" already.)
package MyConfig;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT_OK = qw( $test );
our %EXPORT_TAGS = ( ALL => \#EXPORT_OK );
our $test = "stackoverflow";
1;
main.pl:
use strict;
use warnings;
use MyConfig qw( :ALL );
print "$test\n";