What does "1;" mean in Perl? - perl

I have come across a few Perl modules that for example look similar to the following code:
package MyPackage;
use strict;
use warnings;
use constant PERL510 => ( $] >= 5.0100 );
require Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw( );
{ #What is the significance of this curly brace?
my $somevar;
sub Somesub {
#Some code here
}
}
1;
What is the significance of 1; and of the curly braces that enclose the $somevar and the Sub?

1 at the end of a module means that the module returns true to use/require statements. It can be used to tell if module initialization is successful. Otherwise, use/require will fail.
$somevar is a variable which is accessable only inside the block. It is used to simulate "static" variables. Starting from Perl 5.10 you can use keyword state keyword to have the same results:
## Starting from Perl 5.10 you can specify "static" variables directly.
sub Somesub {
state $somevar;
}

When you load a module "Foo" with use Foo or require(), perl executes the Foo.pm file like an ordinary script. It expects it to return a true value if the module was loaded correctly. The 1; does that. It could be 2; or "hey there"; just as well.
The block around the declaration of $somevar and the function Somesub limits the scope of the variable. That way, it is only accessible from Somesub and doesn't get cleared on each invocation of Somesub (which would be the case if it was declared inside the function body). This idiom has been superseded in recent versions of perl (5.10 and up) which have the state keyword.

Modules have to return a true value. 1 is a true value.

Perl modules must return something that evaluates to true. If they don't, Perl reports an error.
C:\temp>cat MyTest.pm
package MyTest;
use strict;
sub test { print "test\n"; }
#1; # commented out to show error
C:\temp>perl -e "use MyTest"
MyTest.pm did not return a true value at -e line 1.
BEGIN failed--compilation aborted at -e line 1.
C:\temp>
Although it's customary to use "1;", anything that evaluates to true will work.
C:\temp>cat MyTest.pm
package MyTest;
use strict;
sub test { print "test\n"; }
"false";
C:\temp>perl -e "use MyTest"
C:\temp> (no error here)
For obvious reasons another popular return value is 42.
There's a list of cool return values maintained at http://returnvalues.useperl.at/values.html.

The curly braces limit the scope of the local variable $somevar:
{
my $somevar;
...
} # $somevar's scope ends here

From the documentation for require:
The file must return true as the last
statement to indicate successful
execution of any initialization code,
so it's customary to end such a file
with 1; unless you're sure it'll
return true otherwise. But it's better
just to put the 1; , in case you add
more statements.

I don't know much about Perl, but usually you create a scope using curly braces. Probably $somevar shoudln't be available globally?

Related

Perl eval scope

According to perldoc, String Eval should be performed in the current scope. But the following simple test seems to contradict this.
We need the following two simple files to set up the test. Please put them under the same folder.
test_eval_scope.pm
package test_eval_scope;
use strict;
use warnings;
my %h = (a=>'b');
sub f1 {
eval 'print %h, "\n"';
# print %h, "\n"; # this would work
# my $dummy = \%h; # adding this would also work
}
1
test_eval_scope.pl
#!/usr/bin/perl
use File::Basename;
use lib dirname (__FILE__);
use test_eval_scope;
test_eval_scope::f1();
When I run the program, I got the following error
$ test_eval_scope.pl
Variable "%h" is not available at (eval 1) line 1.
My question is why the variable %h is out of scope.
I have done some modification, and found the following:
If I run without eval(), as in the above comment, it will work.
meaning that %h should be in the scope.
If I just add a seemingly useless mentioning in the code, as in the above
comment, eval() will work too.
If I combine pl and pm file into one file, eval() will work too.
If I declare %h with 'our' instead of 'my', eval() will work too.
I encountered this question when I was writing a big program which parsed user-provided code during run time. I don't need solutions as I have plenty workarounds above. But I cannot explain why the above code doesn't work. This affects my perl pride.
My perl version is v5.26.1 on linux.
Thank you for your help!
Subs only capture variables they use. Since f1 doesn't use %h, it doesn't capture it, and %h becomes inaccessible to f1 after it goes out of scope when the module finishes executing.
Any reference to the var, including one that's optimized away, causes the sub to capture the variable. As such, the following does work:
sub f1 {
%h if 0;
eval 'print %h, "\n"';
}
Demo:
$ perl -M5.010 -we'
{
my $x = "x";
sub f { eval q{$x} }
sub g { $x if 0; eval q{$x} }
}
say "f: ", f();
say "g: ", g();
'
Variable "$x" is not available at (eval 1) line 1.
Use of uninitialized value in say at -e line 8.
f:
g: x

Symbolic reference to sub in a package, trying to understand

use strict;
use warnings;
package Foo::Bar;
sub baz { print "$_[0]\n" }
package main;
{ # test 1
my $quux = "Foo::Bar::baz";
no strict 'refs';
&$quux(1);
}
{ # test 2
my $qux = 'Foo::Bar';
my $quux = "$qux\::baz";
no strict 'refs';
&$quux(2);
}
{ # test 3
my $qux = 'Foo::Bar';
my $quux = "$qux::baz";
no strict 'refs';
&$quux(3);
}
Output:
Name "qux::baz" used only once: possible typo at test31.pl line 21.
1
2
Use of uninitialized value $qux::baz in string at test31.pl line 21.
Undefined subroutine &main:: called at test31.pl line 23.
Why does test 2 work, and why does backslash has to be placed exactly there?
Why does test 3 not work, is it so far, in syntax, from test 1?
I tried to write that string as "{$qux}::baz", but it doesn't work, too.
I came across this looking at source of Image::Info distribution.
$qux::baz refers to scalar baz in package qux.
"$qux::baz" is the stringification of that scalar.
"$qux::baz" is another way of writing $qux::baz."".
Curlies can be used to indicate where the variable ends.
"$foo bar" means $foo." bar"
"${f}oo bar" means $f."oo bar"
As such,
"${qux}::baz" is another way of writing $qux."::baz".
"$qux\::baz" is a cute way of doing $qux."::baz" since \ can't appear in variable names.
A variable name can either be simple like $foo or a fully qualified name (in the case of package variables). Such a fully qualified name looks like $Foo::bar. This is the “global” variable $bar in the package Foo.
If an interpolated variable is to be followed by a double colon :: and the variable should not be interpreted as a fully qualified package variable name, then you can either:
Use string concatenation: $qux . "::baz"
Terminate the variable name with a backslash: "$qux\::baz"
Surround the variable name (not the sigil) with curly braces, as if the name were a symbolic reference: "${qux}::bar".

How can I use "member" variables of a module inside a function?

I have this code:
#!/usr/bin/perl
package Modules::TextStuff;
use strict;
use warnings;
use Exporter;
our #ISA = qw(Exporter);
our #EXPORT = qw(get_text);
my $author;
my $text_tmp1 =<<'ENG';
This is a template text
by $author.
ENG
sub get_text {
my $tmp = shift #_;
$author = shift #_;
print "In sub author= $author lang = $tmp \n";
my $final_str = eval('$text_'.$tmp);
print "$final_str \n";
return $final_str;
}
1;
Test script:
#!/usr/bin/perl
use strict;
use warnings;
use Modules::TextStuff;
my $str = get_text('tmp1','jim');
print $str;
When I run the test script it does not work. I get:
In sub author=jim lang = eng
Variable "$text_tmp1" is not available at (eval 1) line 2. Use of
uninitialized value $final_str in concatenation (.) or string
How can I fix this?
Combining strings to create variables names is usually a bad idea. You could salvage your current program using our $text_tmp1 = ... instead of my $text_tmp1 = ..., but I think you should consider a different approach, like a hash:
my %templates = (
tmp1 => <<ENG,
This is a template text
by \$author.
ENG
tmp2 => <<ESP,
Esta es templata texta de \$author.
ESP
);
sub get_text {
...
my $final_str = eval( $templates{$tmp} );
...
}
The error you asked about is generated when eval EXPR tries to grab the value of a variable that did exist, but no longer exists.
>perl -wE"{ my $x = 123; sub f { eval '$x' } } say '<'.f().'>';"
Variable "$x" is not available at (eval 1) line 2.
Use of uninitialized value in concatenation (.) or string at -e line 1.
<>
Remember, executing a file (such as a script or a module) is done in its own a lexical scope, just like the one the curlies create above.
It can be fixed by keeping the variable alive by not letting it go out of scope
>perl -wE"my $x = 123; sub f { eval '$x' } say '<'.f().'>';"
<123>
But that's not an option for you.
Other options include making the variable a global variable.
>perl -wE"{ our $x = 123; sub f { eval '$x' } } say '<'.f().'>';"
<123>
Or forcing the sub to capture it so it doesn't cease to exist.
>perl -wE"{ my $x = 123; sub f { $x if 0; eval '$x' } } say '<'.f().'>';"
<123>
(The if 0 silences the "void context" warning.)
That said, it looks like you're trying to re-invent the wheel. Don't invent another half-assed templating system.
I'm looking at several things:
First of all, $text_tmp1 is not a package variable. It's lexically scoped since you declared it with my. If you need it as a package variable and for it to be visible in all or your subroutines, you need to declare it with our.
Your module doesn't compile as written. You are trying to source in $author, but it's not defined.
What are you doing with eval? This is wrong on so many levels.
Here's how I would do it:
#! /usr/bin/env perl
package Modules::TextStuff;
use strict;
use warnings;
use Exporter qw(import);
use Carp;
our #EXPORT_OK = qw(get_text);
our %templates; # This is now a package variable
#
# TEMPLATES
#
$templates{tmp1}=<<TEMPLATE; # We'll use `%s` for replacements
This is a template text
by %s.
TEMPLATE
$templates{tmp2}=<<TEMPLATE;
This is another template and we will substitute
in %s in this one too.
TEMPLATE
sub get_text {
my $template = shift;
my $author = shift;
if ( not exists $templates{$template} ) {
croak qq(Invalid template name "$template");
}
return sprintf $templates{$template}, $author;
}
1;
I'll make each of these templates an entry in my %templates hash. No need for eval to calculate out a variable name for the template. Also notice that I can now actually test whether the user passed in a valid template or not with the exists.
Also note that %template is declared with our and not my. This makes it available in the entire package including any subroutines in my package.
I also use #EXPORT_OK instead of #EXPORT. It's considered more polite. You're requesting permission to pollute the user's namespace. It's like knocking on someone's door and asking if you can have a beer rather than barging in and rummaging through their fridge for a beer.
Note how I use sprintf to handle the replaceable parameters. This again removes the need for eval.
I also prefer to use #! /usr/bin/env perl on my program header since it's more compatible with things like Perlbrew. You're using /usr/bin/env to find the executable Perl program that's in the user's path. This way, you don't have to know whether it's /bin/perl, /usr/bin/perl, /usr/local/bin/perl, or $HOME/perl5/perlbrew/perls/perl-5.18.0/bin/perl
To use your module, I would do this:
#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
use Modules::TextStuff qw(get_text);
say get_text('tmp1','jim');
Pretty much the same call you made. This prints out:
This is a template text
by jim.

Dependency between perl modules

Suppose I have three perl modules as given below :
Test.pm
package Test;
use strict;
use warnings;
use Check;
our $data = Check->getX;
1;
Initialize.pm
package Initialize;
use Check;
use Test;
Check->setX(10);
our $t = $Test::data;
print $t;
1;
Check.pm
package Check;
my $x = 12;
sub setX {
my ($self,$value) = #_;
$x = $value;
}
sub getX
{
return $x;
}
1;
Now, when I run Initialize.pm, I am initializing $x in Check.pm to 10 and $x is assigned to $data in Test.pm. But the the actual valuethat is assigned to $data is 12 which is the initial value given in Check.pm.
So, When are the global variables initialized in perl? How can I enforce that the new value set by me in the Initialize.pm to x is what is loaded into $data?
Now if I replace the statement use Test in Initalize.pm with require Test; and move the statement Check->setX(10) before this require statement then $data is correctly initialized to the new value 10. What is it that is happening differently in this case ?
In general modules have little or no executable code. Object-oriented modules just define the object methods, and sometimes some class data.
When you use Test the whole of Test.pm is compiled and executed, so the value of $data is set at this point.
The call to setX happens straight afterwards, but is too late to affect the asignment of $data.
As I said in my comment your code has a very odd structure, and modules shouldn't have a time dependency on each other at all. You should really remove all executable statements from your modules, but to force your code to do what you want you can write
use strict;
use warnings;
use Check;
BEGIN {
Check->setX(10);
}
use Test;
our $t = $Test::data;
print $t;
But don't do that!
Perl executes a use statement prior to executing anything else in the file.
So the execution order is:
use Check;
$x = 12;
use Test;
use Check; -This only does importing as the file is already executed
$data = Check->getX();
Check->setX(10);
If you replace use with require the instruction is evaluated at the same time as the rest of the instructions and if you move Check->setX(10); before the require it will be evaluated before the get in Test

In Perl, how do you detect if bignum support is loaded in versions before 5.9.4?

Perl's bignum bigint and bigrat pragmas helpfully contain an in_effect function that will detect if the pragma is loaded into a scope by probing the hints hash. However, this only works in version 5.9.4 and later of perl, since that's when the lexical hints hash was introduced.
Is there any good way of determining if these pragmas are in effect in earlier versions of perl? For my uses, I would like to support back to version 5.8.8.
Update: mob's solution below will work if I had access to the lexical space where bignum may be in effect. However, for my use case, I am writing a function that will be called from that space, and inside that function I need to determine if the caller's scope has bignum loaded. (ie, in my code I am calling something like bignum::in_effect(2) to look a few frames up the call stack)
sub test_sub {is_bignum_in_effect_in_the_caller}
# bignum::in_effect(1) in 5.9.4+
test_sub(); # no bignum
{use bignum; test_sub()} # yes bignum
I don't know if this qualifies as a 'good' way, but you can do a simple operation and see if you are getting the bigint/bigrat result or the conventional Perl result.
$bigint_enabled = length(1E20) == 21; # conventional result is 5
At the risk of making this answer even less good, how can you determine whether bigint is enabled in the caller's scope?
One. Require the caller to tell you whether bignum is enabled.
# your package
package Foo;
use base 'Exporter';
use bigint;
our #EXPORT = qw($BIGINT_TEST multiply);
our $BIGINT_TEST = $]>=5.009004
? "bigint::in_effect()"
: "\$bigint::VERSION<0.22 || length(1E20)==21";
sub multiply {
my ($arg1, $arg2, $bigint_enabled) = #_;
if ($bigint_enabled) {
use bigint;
return $arg1*$arg2;
} else {
no bigint;
return $arg1*$arg2;
}
}
# user program
use Foo;
use bigint;
print "Enabled: ", multiply(1E15,1E10, eval $BIGINT_TEST), "\n";
{
no bigint;
print "Disabled: ", multiply(1E15,1E10,eval $BIGINT_TEST), "\n";
}
# result
$ perl510 user_program.pl
Enabled: 10000000000000000000000000
Disabled: 1e+25
$ perl587 user_program.pl ($bignum::VERSION eq 0.07)
Enabled: 10000000000000000000000000
Disabled: 10000000000000000000000000
$ perl588 user_program.pl (includes upgrade to bignum 0.25)
Enabled: 10000000000000000000000000
Disabled: 1e+25
Two. Source filtering? Hack the op tree? Use either of these methods to insert an argument to the method call or to set a global variable prior to the method call.