Specal Handling of Base.pm? - perl

I create a module called Base.pm in the same directory as the Perl program that wants to use it but the module doesn't seem to be loaded. Change the name of the module to anything other than Base and things work just fine. What is special about Base.pm and how does one override this behavior? Thanks for any insight.
package Base;
use strict;
use Exporter;
use vars qw($VERSION #ISA #EXPORT #EXPORT_OK %EXPORT_TAGS);
$VERSION = 1.00;
#ISA = qw(Exporter);
#EXPORT = qw(func);
sub func { return "foo"; }
1;
with
use Base;
print func();
yields
Undefined subroutine &main::func called at test0.pl line 2.
whereas
package Case;
use strict;
use Exporter;
use vars qw($VERSION #ISA #EXPORT #EXPORT_OK %EXPORT_TAGS);
$VERSION = 1.00;
#ISA = qw(Exporter);
#EXPORT = qw(func);
sub func { return "foo"; }
1;
with
use Case;
print func();
yields
foo.

base.pm is a core system "pragma" module (these days, it's deprecated for parent.pm)
use base 'MyBaseClass'; # Same as: our #ISA = ( 'MyBaseClass' );
It's probably a Windows case thing. Perl looks for "Base.pm", but windows returns "base.pm". When you named it "anything other than Base", you probably didn't rename it to another Perl module.
One way you can check this is to run the following:
use Data::Dumper
print a dump of %INC (a map of all loaded modules and where they were loaded from)
use Data::Dumper;
...
use Base;
...
print Dumper( \%INC );
Look for 'base.pm' or 'Base.pm' to see what Perl loaded.

Inspect %INC to see what's actually being loaded:
use Base;
print $INC{'Base.pm'};
Outputs:
/Users/miller/perl5/perlbrew/perls/perl-5.20.0/lib/5.20.1/Base.pm
I'm on a non-case sensitive OSX partition, so this file corresponds to the base pragma.
To avoid this type of issue, give your projects a private namespace. This way there's less risk of conflicting with a current or future Perl Core or CPAN module:
package MyProject::Base;

Related

Can't use Exporter properly

I've wasted many days on a larger block of code, containing Exporter statements, which used to work about a year ago. Several variations on this have failed, including an install of ./FOO/BAR/Foobar.pm which signaled success.
I am using Windows 10, Perl v5.26.0, built for MSWin32-x64-multi-thread
Caller.pl
#!/usr/bin/perl
use lib ".";
use lib "./FOO/BAR";
use strict;
use warnings;
use FOO::BAR::Foobar;
print "try FOO::BAR::Foobar::foo()\n";
FOO::BAR::Foobar::foo(); # perl can't find this
print "try foo()\n";
foo(); # errors out - can't find &main::foo
print "done\n";
./FOO/BAR/Foobar.pl
#!/usr/bin/perl -w
use strict;
use warnings;
package Foobar;
our($VERSION , #ISA , #EXPORT , #EXPORT_OK , %EXPORT_TAGS , $FOO);
BEGIN {
require Exporter;
#ISA = qw(Exporter);
#EXPORT_OK = qw(foo);
}
sub foo {
print "Loaded\n";
$FOO = q{some val};
}
1;
Execution dump
perl Caller.pl
try FOO::BAR::Foobar::foo()
Undefined subroutine &FOO::BAR::Foobar::foo called at Caller.pl line 12.
What's going on? Should I abandon any use of Exporter? But then how to link functions across modules?
There are three things going wrong:
With FOO::BAR::Foobar::foo(): There is no such sub, there is only Foobar::foo().
With foo(): use FOO::BAR::Foobar; is the equivalent of BEGIN { require FOO::BAR::Foobar; FOO::BAR::Foobar->import() }, but there is no method import available in the package FOO::BAR::Foobar, since you're inheriting Exporter into the package Foobar.
With foo(): You're using #EXPORT_OK instead of #EXPORT, which means that you need to explicitly import foo, but you're not doing that in use FOO::BAR::Foobar;.
So two things are needed to fix this:
As already pointed out in the comment by #HåkonHægland, change package Foobar; to package FOO::BAR::Foobar;.
Change use FOO::BAR::Foobar; to use FOO::BAR::Foobar qw/foo/;.
Then the code you've shown will work - there's no need to abandon Exporter. I'd just recommend a different style of using Exporter: Instead of inheriting via #ISA, just import import into your package. Here's how I would have written your file ./FOO/BAR/Foobar.pm:
package FOO::BAR::Foobar;
use strict;
use warnings;
use Exporter 'import';
our #EXPORT_OK = qw(foo);
our $FOO;
sub foo {
print "Loaded\n";
$FOO = q{some val};
}
1;

Perl: script and module calling a second module

I have the following:
Module1
package module1;
require Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw(<list of subs within>);
use Module2;
sub M1S1 ()
{
$x = M2S1();
}
Module 2
package module2;
require Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw(<list of modules within>);
sub M2S1()
{
...
}
sub M2S2()
{
...
}
Script
use Module2;
use Module1;
$y = M1S1();
$z = M2S2();
When the script calls a sub in Module 1 which in turn calls a sub in Module 2, the sub is not found, even though the script can call those subs directly.
I'm not a beginner to Perl by any means, but I've never fully gotten the hang of modules. Our environment has gotten very dependent on module2, so I don't want to make any changes that would require changing all the scripts that use it. Module1 has limited use so I can make changes to it if necessary.
The file name, the name in the package directive, and the name in the use statement must match, and that includes case.
Module1.pm
package Module1;
use Module1;
Or if you had a non-flat namespace,
Foo/Bar.pm
package Foo::Bar;
use Foo::Bar;
Note that you can have similar problems when you have two exporting modules that use each other (directly or indirectly), but that doesn't seem to the case.
$ cat Module1.pm
package Module1;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT = qw( M1S1 );
use Module2;
sub M1S1 { M2S1() }
1;
$ cat Module2.pm
package Module2;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT = qw( M2S1 M2S2 );
sub M2S1 { "M2S1" }
sub M2S2 { "M2S2" }
1;
$ cat script.pl
#!/usr/bin/perl
use strict;
use warnings;
use Module2;
use Module1;
print(M1S1(), "\n");
print(M2S2(), "\n");
$ ./script.pl
M2S1
M2S2

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;

how to export names when package name is different from file name?

I have a file Scanners.pm which contains 2 packages. I want both these packages to export some names. I do not want those packages be in separate files, I want them to be in one file.
When I write
package SCAN;
use Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw(#SCANNERS #NAMES %NAMES name_index process_scanners);
our #EXPORT_OK = qw();
and then in the calling .pl file
use Scanner;
the names in the #EXPORT list are not exported. How I do that?
You can create a custom import sub for your Scanner package. Exporting Without Using Exporter's import Method.
Note, this code only will work if the user relies on the default #EXPORT only. If you want them to be able to specify what functions they want, then you'll have to filter before calling export_to_level.
package Scanner;
use Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw(scannersub);
use strict;
use warnings;
sub import {
Scanner->export_to_level(1, #_);
ScannerTwo->export_to_level(1, #_);
}
sub scannersub {
print "scanner->sub says hi\n";
}
package ScannerTwo;
use Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw(scannertwosub);
sub scannertwosub {
print "scannertwo->sub says hi\n";
}
1;
__END__
and your script
use Scanner;
use strict;
use warnings;
scannersub();
scannertwosub();
1;
__END__
Finally, I would be remis if I didn't mention that this isn't a great idea on it's surface. Future maintainers of this code will not easily be able to trace these subs. So whatever your reason for wanting them in the same file but different packages, I suspect there is a better solution.

Why don't functions from package A get imported into package B when they recursively call each other?

I'm trying to use two packages and call functions from one to other, but I've got this error:
Undefined subroutine &module2::method_1_2 called at module2.pm line 20.
Is there any way to call functions from one package to the other one without getting this error?
Thanks in advance.
xabi
exec error:
./test.pl
method_1_1
method_2_1
method_2_2
Undefined subroutine &module2::method_1_2 called at module2.pm line 20.
Sample code (test.pl):
#!/usr/bin/perl
use strict;
use module1;
use module2;
method_1_1();
method_2_2();
module1.pm
package module1;
use strict;
use module2;
require Exporter;
use vars qw(#ISA #EXPORT);
#ISA = qw(Exporter);
#EXPORT = qw( method_1_1 method_1_2 );
sub method_1_1
{
print "method_1_1\n";
method_2_1();
}
sub method_1_2
{
print "method_1_2\n";
}
1;
module2.pm:
package module2;
use strict;
use module1;
require Exporter;
use vars qw(#ISA #EXPORT);
#ISA = qw(Exporter);
#EXPORT = qw( method_2_1 method_2_2 );
sub method_2_1
{
print "method_2_1\n";
}
sub method_2_2
{
print "method_2_2\n";
method_1_2();
}
1;
The problem is that the very first thing module1 does is to use module2. That means all of module2 is read and executed while module1 is still compiling.
The next thing to happen is that module2 does use module1. Because module1 has been found and put into %INC Perl doesn't execute it again, and just does module1->import to fetch the exported symbols.
But of course module1 has in fact barely started compiling, and #module1::EXPORT doesn't even exist, never mind about its two subroutines. That makes Exporter import nothing at all into module2, so when it comes to make the call method_1_2() it knows nothing about it.
The cleanest way to fix this is to do the import after the compilation (including all the use statements and BEGIN blocks) but before runtime. Perl's INIT block is ideal for this, and we can get the code working by changing the modules to the form below. I have shown only module2 here, as the pattern of calls means this is all that's needed to fix this particular problem, but the general case needs the equivalent change to all cooperating modules.
package module2;
use strict;
use warnings;
use module1;
INIT { module1->import }
use base 'Exporter';
our #EXPORT = qw( method_2_1 method_2_2 );
sub method_2_1 {
print "method_2_1\n";
}
sub method_2_2 {
print "method_2_2\n";
method_1_2();
}
1;
The problem is that you assign to #EXPORT after it was already used. The following is copied from Mini-Tutorial: Mutual Use of Exporting Modules
[ The need to use this technique is a very strong indicator of a design flaw in your system, but I recognize that the resources are not always available to fix design flaws. ]
If ModA uses ModB, ModB uses ModA, and ModA or ModB imports symbols from the other, one needs to pay attention to code execution order. The best way I've found to avoid problems is to setup Exporter before loading any other module.
# ModA.pm
package ModA;
use strict;
use warnings;
use Exporter qw( import );
BEGIN { our #EXPORT_OK = qw( ... ); }
use This;
use ModB;
use That;
...
1;
# ModB.pm
package ModB;
use strict;
use warnings;
use Exporter qw( import );
BEGIN { our #EXPORT_OK = qw( ... ); }
use This;
use ModA;
use That;
...
1;
Interesting, I am not sure why method_1_2 isn't being exported into the module2 namespace, but you can get around this by explicitly referencing the package:
module1.pm
package module1;
use strict;
use warnings;
use module2 (); #don't import methods
use base 'Exporter';
our #EXPORT = qw( method_1_1 method_1_2 );
sub method_1_1
{
print "method_1_1\n";
module2::method_2_1();
}
sub method_1_2
{
print "method_1_2\n";
}
1;
module2.pm
package module2;
use strict;
use warnings;
use module1 (); #don't import methods
use base 'Exporter';
our #EXPORT = qw( method_2_1 method_2_2 );
sub method_2_1
{
print "method_2_1\n";
}
sub method_2_2
{
print "method_2_2\n";
module1::method_1_2();
}
1;
Okay, I think I see what is going on, but take this with a grain of salt. The use function is effectively a BEGIN block and BEGIN blocks run as soon as they are parsed, so the code looks like this in execution order.
perl starts parsing test.pl
it sees use module1; so it loads module1.pm and starts parsing it
perl sees use module2; in module1.pm so it loads module2.pm and starts parsing it
At this point, the functions in module1 do not yet exist, so they can't be imported
parsing continues
Something Borodin said tipped me off to the best solution: "#module1::EXPORT doesn't even exist". The problem here is that the #EXPORT variable doesn't exist. This can be fixed by putting it in a BEGIN block:
module1.pm
package module1;
use strict;
use warnings;
use base 'Exporter';
BEGIN {
our #EXPORT = qw( method_1_1 method_1_2 );
}
use module2;
sub method_1_1
{
print "method_1_1\n";
module2::method_2_1();
}
sub method_1_2
{
print "method_1_2\n";
}
1;
module2.pm
package module2;
use strict;
use warnings;
use base 'Exporter';
BEGIN {
our #EXPORT = qw( method_2_1 method_2_2 );
}
use module1;
sub method_2_1
{
print "method_2_1\n";
}
sub method_2_2
{
print "method_2_2\n";
method_1_2();
}
1;
IMPORTANT NOTE: I do not believe prototypes in module1 will be honored in any of these cases (and I don't see how they could be since module2 gets compiled before module1, so it can't know the prototypes exist). This is yet another argument to never use prototypes.