Using lib pragma after explicitly setting #INC has no effect - perl

use feature qw(say);
use strict;
use warnings;
BEGIN {
#INC = qw(dir1 dir2); # <-- lib pragma works fine if I omit this line
# #INC = (); <-- this is what I wanted to do
use lib 'dir3';
}
say for #INC;
Output:
dir1
dir2
Expected output:
dir3
dir1
dir2

A use statement is contained within an implicit BEGIN block, and
all Perl BEGIN blocks in a program are are executed as soon as they finish compilation
That means you have nested BEGIN blocks here, and because the inner one—the use lib 'dir3' statement—finishes compilation at the end of the statement, it is the first to be executed. It is followed by the closing brace of the explicit BEGIN block, which completes that block's compilation and it is only then that those statements are executed
Here is a sample program that uses only say statements, and replaces the use statement in the original with an explicit BEGIN block
use strict;
use warnings;
use feature 'say';
BEGIN {
say "outer BEGIN";
BEGIN {
say "inner BEGIN";
}
}
output
inner BEGIN
outer BEGIN
Your code works as if you had written it like this
use feature qw(say);
use strict;
use warnings;
use lib 'dir3';
BEGIN {
#INC = qw(dir1 dir2);
}
say for #INC;
So the use lib is executed first, adding dir3 to #INC, and then the explicit BEGIN block is executed and overwrites #INC altogether
If you want to empty #INC first and then add to it with use lib statements then you should write
BEGIN {
our #INC = ( );
}
use lib 'dir3';
Without the nesting, BEGIN blocks are executed in the order the appear in the program

From perldoc - lib
This is a small simple module which simplifies the manipulation of #INC at compile time.
When you insert say for #INC; after the opening brace and before the assignment, e.g.
BEGIN {
say for #INC;
#INC = qw(dir1 dir2); # <-- lib pragma works fine if I omit this line
# #INC = (); <-- this is what I wanted to do
use lib 'dir3';
}
You will see dir3 listed.
And perldoc - use states
Because use takes effect at compile time, it doesn't respect the ordinary flow control of the code being compiled.
dir3 is inserted into #INC before anything else is executed, and then #INC is assigned the new value (dir1, dir2). You see this new assigned value, when you look at #INC finally.

Related

Is the order of use of perl modules followed when evaluating subroutines?

I have a perl module that has a frequently used subroutine. For a specific set of scripts I need to override this subroutine so i created another module that has the new implementation. Does anyone know if the call order of the perl modules are always followed?
Ex.:
one.pm:
sub temp{ print “hi”; }
two.pm:
sub temp{ print “hello”; }
sample.pl:
use one; use two;
temp();
I have tested this and it prints “hello” as expected. But I wanted to make sure that this is always the case. Is the evaluation of imported modules in order all the time?
You should not write modules like that! Your just going to get into problems, including the one you're asking about. Any file loaded using use should have corresponding package. And they must end on a true value. (Your code doesn't compile because you failed to do so.)
Before I got on, let me mention that you should ALWAYS use use strict; use warnings;. Also note that lowercase module names are traditionally used for pragmas, modules that change how Perl itself behaves. It's a poor practice to use lowercase module names for other purposes.
Back to the point. At a minimum, you need the following:
One.pm:
package One;
use strict;
use warnings;
sub temp { ... }
1;
Two.pm:
package Two;
use strict;
use warnings;
sub temp { ... }
1;
The script would now look like this:
use strict;
use warnings;
use One qw( );
use Two qw( );
One::temp();
Two::temp();
And now you see that your problem is moot; there's no question about which sub is called.
But, what if you didn't want to prefix all the calls with One:: or Two::? We can do that!
One.pm:
package One;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT_OK = qw( temp );
sub temp { ... }
1;
Two.pm:
package Two;
use strict;
use warnings;
use Exporter qw( import );
our #EXPORT_OK = qw( temp );
sub temp { ... }
1;
The script would now look like this:
use strict;
use warnings;
use One qw( );
use Two qw( temp );
One::temp();
Two::temp();
temp(); # Calls Two::temp() because we imported temp from Two.
If you somehow did the following or equivalent, the last one would win out.
use One qw( temp );
use Two qw( temp );
That's why it's good to always list the subs you import. Don't use
use Foo; # Import default exports
Instead, use
use Foo qw( ); # Only import the listed exports. (None, in this case.)
If nothing else, it also makes it a lot easier to find subs and their documentation when maintaining the module.
The last one you compile wins, and use and require statements run in order from top to bottom (including any nesting inside modules that you include).
In this case, you have two module files, neither of which declare a package. Since they don't declare a package, they both use the default package main. Everything these modules define will show up in the main package.
Likewise, your program is also using the default package main, which is how is knows there is a temp subroutine. Since you loaded two.pm last, that's the definition that wins.
Now, let's fix up the code in your question because it doesn't actually work. Neither of those modules will load because neither returns a true value.
Both modules now have the same code because I can use the __FILE__ token to tell me which code ran:
one.pm:
sub temp { print 'From ' . __FILE__ }
1;
two.pm:
sub temp { print 'From ' . __FILE__ }
1;
temp.pl:
use lib qw(.);
use one;
use two;
temp();
Running this outputs the message from two.pm because that's the last one defined:
$ perl temp.pl
From two.pm
Run your program with warnings and you'll see there's a redefinition (which in this case is intentional):
$ perl -w temp.pl
Subroutine temp redefined at two.pm line 1.
From two.pm
The trick, then, is to ensure that your new code always comes last. One way to do this is to load the old module from the new one:
two.pm:
use one;
sub temp { print 'From ' . __FILE__ }
1;
I won't go any further with your example because I figure it's not your actual situation. I do write about these sorts of things in Effective Perl Programming though.
Yes. A use statement is equivalent to:
BEGIN { require Module; Module->import( LIST ); }
And Perl runs all compile time code (BEGIN blocks and use statements) in the order it appears (but before any runtime code is executed):
You may have multiple BEGIN blocks within a file (or eval'ed string); they will execute in order of definition.
What creates the subroutine in the current package is usually that module's import method, which will override any existing subroutines with those names at the time it runs.

substituting variables in BEGIN push #INC

So instead of wanting to put
BEGIN {push #INC , '/folder1', '/folder2', '/folder3'}
to find my module.
I want to be able to put a variable instead such as this.
my $test = '/folder1';
BEGIN {push #INC , $test, '/folder2', '/folder3'}
No matter what I do it still wont find the module I want.
A BEGIN executes during parsing of the code, so it would be executed before a variable assignment outside of it occurs.
The solution is to do the assignment inside the BEGIN block:
my $test;
BEGIN {
$test = "/some/path";
}
use lib $test, "/path2", "path3";
The use lib … is preferable to unshift #INC, …
Instead of manually manipulating #INC, I suggest that you use lib:
use lib '/folder2', '/folder3';
Also, use and BEGIN blocks are executed as soon as possible, so if you want to include a variable in one, it must be initialized in a BEGIN block:
our $test;
BEGIN {
$test = "/some/path";
}
use lib $test, '/folder2', '/folder3';
The BEGIN statement runs before anything else runs -- even if the BEGIN statement appears later in the program. Variables you're using must also appear inside the BEGIN. Any variables declared with my will be out of scope once the BEGIN statement ends.
BEGIN {
my $test = '/folder1';
push #INC, $test, '/folder2', '/folder3';
}
I'm not sure what this is buying you. You still need to modify the program. You may want to use lib;:
use lib qw(/folder1);
use lib qw(/folder2 /folder3);
# use lib qw(/folder4); # Don't use

How do you use a variable in lib Path?

I would like to use the $var variable in lib path.
my $var = "/home/usr/bibfile;"
use lib "$var/lib/";
However when I do this it throws an error.
I'd like to use use lib "$var/lib/";instead of use lib "/home/usr/bibfile/lib/";.
How can I assign a variable, so that it can be used in the setting of lib modules?
Variables work fine in use lib, well, just like they do in any string. However, since all use directives are executed in BEGIN block, your variable will be not yet initialized at the moment you run use, so you need to put initialization in BEGIN block too.
my $var;
BEGIN { $var = "/home/usr/bibfile"; }
use lib "$var/lib/";
use Data::Dumper;
print Dumper \#INC;
Gives:
$VAR1 = [
'/home/usr/bibfile/lib/',
# ... more ...
];
Not sure about what you're trying to accomplish, but seems like a task for FindBin::libs:
my $var;
BEGIN { $var = "/home/usr/bibfile" };
use FindBin::libs "Bin=$var", "base=lib";
You can't, because the use directive is evaluated at compile time, while other variables are evaluated at runtime.
If your lib is located somewhere relative to your original script, you can use the standard module FindBin:
# $Bin from FindBin is the directory of the original script
use FindBin;
use lib "$FindBin::Bin/path/to/bib";
use MyModule;

perlmod question

In the example in perlmod/Perl Modules there is a BEGIN block. I looked at some modules but none of these had a BEGIN block. Should I use such a BEGIN block when writing a module or is it dispensable?
You only need a BEGIN block if you need to execute some code at compile time versus run-time.
An example: Suppose you have a module Foo.pm in a non-standard library directory (like /tmp). You know you can have perl find the module by modifying #INC to include /tmp. However, this will not work:
unshift(#INC, '/tmp');
use Foo; # perl reports Foo.pm not found
The problem is that the use statement is executed at compile time whereas the unshift statement is executed at run time, so when perl looks for Foo.pm, the include path hasn't been modified (yet).
The right way to accomplish this is:
BEGIN { unshift(#INC, '/tmp') };
use Foo;
Now the unshift statement is executed at compile-time and before the use Foo statement.
The vast majority of scripts will not require BEGIN blocks. A lot of what you need in BEGIN blocks can be obtained through use-ing other modules. For instance, in this case we could make sure /tmp is in #INC by using the lib.pm module:
use lib '/tmp';
use Foo;
A BEGIN block in a module is entirely dispensable. You only use it if there is something that must be done by your module when it is loaded, before it is used. There are seldom reasons to do much at that point, so there are seldom reasons to use a BEGIN block.

using files other perl files in another perl file [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
How do I include functions from another file in my Perl script?
I have a perl file suppose a.pl and I want to use a function from perl file b.pl. How do i do it
Turn b.pl into a module
Call it something descriptive like MyBModule (B is reserved by core).
rename the file to the something .pm like MyBModule.pm.
Add a package at the top, like package MyBModule;
Set a true return code on the package by making the last line 1;
You don't have to do anything else if you want to use your package name when calling the sub.
use MyBModule;
use strict;
use warnings;
MyBModule::sub1();
If you don't want to qualify it with the package name, read on...
Use Exporter.pm
Now configure Exporter.
Add the use Exporter; statement at the top of your module.
add a line our #EXPORT_OK = qw(sub1 sub2);
After you're done your module should look something like this
package MyBModule;
use strict;
use warnings;
use Exporter;
our #EXPORT_OK = qw(sub1 sub2);
sub sub1 { ... }
sub sub2 { ... }
Edit the caller
Make sure the library is in #INC, or the module in the current directory. If not append the directory to PERL5LIB.
Add a line like use MyBModule qw(sub1 sub2);
Read perldoc Exporter for more information
Your script should look like this afterward:
use strict;
use warnings;
use MyModuleB qw( sub1 sub2 );
It really isn't that hard, it takes about 15 seconds after you get used to doing it.
The best/conventional way is to keep all your functions in a Perl module file (.pm): See perlmod. This would require you to convert b.pl to a package. You would then access your module file (MyFuncs.pm) from a.pl with:
use MyFuncs;
Use the require and/or use functions.
Use the 'use' keyword to use functions from another module.
Example:
File a.pl:
use b;
f_in_b();
File b.pm:
sub f_in_b()
{
print "f_in_b\n";
}
1;
Important:
File b.pm must have the final 1;