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

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";

Related

Given a number of variables to test for definedness, how to (easily) find out the one which was left undefined?

Today I saw this piece of code:
if ( not defined($reply_address)
or not defined($from_name)
or not defined($subject)
or not defined($date) )
{
die "couldn’t glean the required information!";
}
(Jeffrey Friedl, "Mastering Regular Expressions", p. 59, 3rd ed.)
and I thought "How can I know which variable misfired?"
Of course, if there are only 4 variables to test, as in the example above, one could come up with:
if ( not defined $reply_address )
{
die "\$reply_address is not defined"
}
elsif ( not defined $from_name )
{
die "\$from_name is not defined"
}
elsif ...
But what if there are 14 variables? Or 40...?
One still needs to go through all of them, manually testing each and every one?
Isn't there a shorter, more "magical" way of telling which variable was left undefined?
You could create a table to simplify a little bit:
use strict;
use warnings;
my $reply_address = "xyz";
my $from_name;
my $subject = "test";
my $date;
my #checks = (
[\$reply_address, '$reply_adress'],
[\$from_name, '$from_name'],
[\$subject, '$subject'],
[\$date, '$date'],
);
for my $check (#checks) {
if (not defined ${$check->[0]}) {
die $check->[1] . " is not defined";
}
}
You can do what you want with symbolic references, though using them is generally not a great idea, and it can only be done with package variables, not lexically scoped variables (and lexically scoped variables are preferred to package variables -- see this answer for a brief comparison of the two).
#!/usr/bin/env perl
use strict;
use warnings;
use 5.014;
our($foo1) = 1;
our($bar1) = undef;
our($baz1) = 3;
foreach my $name (qw(foo1 bar1 baz1)) {
{
no strict 'refs';
my($value) = $$name;
warn "$name: is not defined" unless defined $value;
say "$name: <$value>";
}
}
Using warn instead of die for illustrative purposes.
</tmp> $ ./test.pl
foo1: <1>
bar1: is not defined at ./test.pl line 16.
Use of uninitialized value $value in concatenation (.) or string at ./test.pl line 17.
bar1: <>
baz1: <3>
You can also just loop through all of the variables using common code to check them:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.014;
my($foo2) = 1;
my($bar2) = undef;
my($baz2) = 3;
foreach my $vardef (["foo2", $foo2], ["bar2", $bar2], ["baz2", $baz2]) {
my($name) = $vardef->[0];
my($value) = $vardef->[1];
warn "$name: is not defined" unless defined $value;
say "$name: <$value>";
}
which gives similar output:
foo2: <1>
bar2: is not defined at ./test.pl line 29.
Use of uninitialized value $value in concatenation (.) or string at ./test.pl line 30.
bar2: <>
baz2: <3>
Finally, if you can manage to get the variables into a hash, you can loop through the keys of the hash and test them that way:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.014;
my($vars) = {
foo3 => 1,
bar3 => undef,
baz3 => 3,
};
foreach my $name (sort keys %$vars) {
my($value) = $vars->{$name};
warn "$name: is not defined" unless defined $value;
say "$name: <$value>";
}
I threw the sort in there because I like deterministic behavior...
bar3: is not defined at ./test.pl line 42.
Use of uninitialized value $value in concatenation (.) or string at ./test.pl line 43.
bar3: <>
baz3: <3>
foo3: <1>
If the test really was as simple as die if ! defined then I would probably just list them out:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.014;
my($foo4) = 1;
my($bar4) = undef;
my($baz4) = 3;
die qq([ERROR] \$foo4 not defined\n) unless defined $foo4;
die qq([ERROR] \$bar4 not defined\n) unless defined $bar4;
die qq([ERROR] \$baz4 not defined\n) unless defined $baz4;
which just gives us:
[ERROR] $bar4 not defined
The last approach is just very straightforward and unambiguous. If the test is not as dead simple as this, then I'd go with the second approach. If you're worried about a list of 40 (or even 14) checks of this nature, then I'd look at the design.
See also this PadWalker code example for a very complicated version of the first option, but allowing lexically scoped variables.
Could be done with a string-eval:
use strict;
use warnings;
my ($reply_address, $from_name, $subject, $date) = ('', '', undef, '');
for my $var (qw(reply_address from_name subject date)) {
my $defined;
eval "\$defined = defined \$$var";
die "eval failed: $#" if $#;
die "\$$var is not defined" unless $defined;
}

Issues with subroutine Perl

I'm trying to execute a Perl program, but the window only closes up. But if I select a part of the window, it stays open, and I press Enter and says
Undefined subroutine &genNumeros::crearNumero called at .... at line 17
genNumeros.pm
package genNumeros;
use strict;
use warnings;
use Math::Complex;
my $seed = time();
my $a = $seed / 5;
my $c = $seed - 7;
my $x = $seed;
my $m = sqrt($seed % 574) + $seed;
my $numAleatorio;
sub generadorMultiplicativo {
$numAleatorio = ((($a*$x) + $c) % $m);
$x = $numAleatorio;
}
my $letra;
my $residuo;
sub crearNumero {
generadorMultiplicativo();
$residuo = $x / $m;
return int($residuo * 27)
}
1;
main.pl
#!/usr/bin/perl
use warnings;
use FindBin;
use lib $FindBin::Bin;
use genNumeros;
my #palabra;
open (my $ARCHIVO, '<', "palabras.txt") or die ("No se encontro el archivo palabras.txt, $!");
while (my $palabra = <$ARCHIVO>) {
chomp $palabra;
push #palabra, $palabra;
}
close $ARCHIVO;
my $palabraAleatoria = $palabra[ genNumeros::crearNumero() ];
print "$palabraAleatoria\n";
<>;
Your package name and the corresponding file name should use capital letters, and local names should be all lower case
So your library should be in file GenNumeros.pm, and should start with package GenNumeros
It should define subroutines generador_multiplicativo and crear_numero
Your main program file should use GenNumeros
The usual way to import identifiers is to use Exporter in your library code, but fully-qualifying the subroutines, like GenNumeros::generador_multiplicativo is also fine

Initializing Perl variables using eval

I'm guessing this should be something obvious to those knowing Perl, but I simply don't get it... I also guess it has to do with problems described in Perl scoping « darkness - but I cannot apply any of that in my case.
Anyway, here's the code:
#!/usr/bin/env perl
# call with:
# ./test.pl
use strict;
my $tvars = "my \$varA = 1;
my \$varB = 2;
my \$varC = 3;
";
my #lines = split /\n/, $tvars;
foreach my $line (#lines) {
print "$line\n";
eval $line; warn $# if $#;
}
#~ print "$varA\n"; # Global symbol "$varA" requires explicit package name at ./test.pl line 18.
#~ print "$varB\n"; # Global symbol "$varB" requires explicit package name at ./test.pl line 19.
#~ print "$varC\n"; # Global symbol "$varC" requires explicit package name at ./test.pl line 20.
$tvars = "our \$varA = 1;
our \$varB = 2;
our \$varC = 3;
";
#lines = split /\n/, $tvars;
foreach my $line (#lines) {
print "$line\n";
eval $line; warn $# if $#;
}
print "$varA\n"; # Global symbol "$varA" requires explicit package name at ./test.pl line 33.
print "$varB\n"; # Global symbol "$varB" requires explicit package name at ./test.pl line 34.
print "$varC\n"; # Global symbol "$varC" requires explicit package name at ./test.pl line 35.
Simply speaking, I'd like to have something like "$varA = 1;" written as a string (text file); and I'd like perl to eval it, so that afterwards I have access to variable "$varA" in the same script - the errors I get when I try to access those after an eval are in the comments of the code above (however, no warnings are reported during the eval). (I'm guessing, what I'd need is something like "global" variables, if the eval runs in a different context than the main script?)
How would I go about doing that? Do I have to go through all of that package definition business, even for a simple script like the above?
It has everything to do with scoping. The variables are declared with my inside the eval expression. This makes them local to the eval statement and not accessible once the eval statement exits. You can declare them first, though:
my ($varA, $varB, $varC); # declare outside the eval statement
my $tvars = "\$varA = 1;
\$varB = 2;
\$varC = 3;
";
eval $tvars;
# local $varA, $varB, $varC variables are now initialized
or as you suggest, you can use global variables. The easiest (though not necessarily the "best" way) is to prepend :: to all variable names and get them in the main package.
my $tvars = "\$::varA = 1;
\$::varB = 2;
\$::varC = 3;
";
eval $tvars;
print "A=$::varA, B=$::varB, C=$::varC\n";
Now when you tried our variables in your example, you actually were initializing package (global) variables. But outside the eval statement, you still need to qualify (i.e., specify the package name) them in order to access them:
$tvar = "our \$foo = 5";
eval $tvar;
print $main::foo; # ==> 5
The problem is that when you do eval $string, $string is evaluated as its own subroutine which has its own lexical scope. From perldoc -f eval:
In the first form [in which the argument is a string], the return value of EXPR is parsed and
executed as if it were a little Perl program. The value of the expression (which is itself
determined within scalar context) is first parsed, and if there were no errors, executed in the
lexical context of the current Perl program, so that any variable settings or subroutine and format
definitions remain afterwards.
So, in other words, if you have:
use strict;
use warnings;
eval "my $foo=5;";
print "$foo\n";
you'll get an error:
Global symbol "$foo" requires explicit package name at -e line 3.
Global symbol "$foo" requires explicit package name at -e line 4.
However, if you initialize your variables first, you're fine.
use strict;
use warnings;
my $foo;
eval "\$foo=5;";
print "$foo\n"; #prints out 5, as expected.

Can I dynamically get a list of functions or function names from any Perl module?

I would like to dynamically get a list of either function names (as strings) or function references from any arbitrary Perl module available on my system. This would include modules that may or may not have, e.g., a global #EXPORT_OK array in its namespace. Is such a feat possible? How does one pull it off if so?
Edit: From reading perlmod, I see that %Some::Module:: serves as a symbol table for Some::Module. Is this the correct place to be looking? If so, how can I whittle the table down to just the function names in Some::Module?
You're on the right track. To wittle down the full symbol table to just the subs, something like this can be done (Hat tip "Mastering Perl", ch 8, for main package version of this):
use strict; # need to turn off refs when needed
package X;
sub x {1;};
sub y {1;};
our $y = 1;
our $z = 2;
package main;
foreach my $entry ( keys %X:: ) {
no strict 'refs';
if (defined &{"X::$entry"}) {
print "sub $entry is defined\n" ;
}
}
# OUTPUT
sub y is defined
sub x is defined
You may find this simple script handy:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
# dump of object's symbol table:
foreach my $className (#ARGV)
{
print "symbols in $className:";
eval "require $className";
die "Can't load $className: $#" if $#;
no strict 'refs';
print Dumper(\%{"main::${className}::"});
}
But, if you're doing this in production code, I'd use Package::Stash instead:
my #subs_in_foo = Package::Stash->new('Foo')->list_all_symbols('CODE');
I'm using Perl 5.20. This works on my machine:
use strict;
package foo;
our $some_var;
sub func1 { return 'func1'}
sub func2 { return 'func2'}
package main;
sub callable {
my ($x) = #_;
return defined(&$x);
}
while (my ($k, $v) = each(%foo::)) {
if (callable($v)) {
print("$k\n");
}
}
# output:
# func1
# func2

How can I create a Perl variable name based on a string?

In Perl, is it possible to create a global variable based on a string?
E.g., if I had a function like:
sub create_glob_var {
my ($glob_var_str) = #_;
# something like this ( but not a hash access).
our ${$glob_var_str};
};
and I called it like:
create_glob_var( "bar" );
How could I modify create_glob_var to actually create a global variable called $bar?
My project is using perl 5.8.5.
EDIT
The following doesn't work:
use strict;
BEGIN {
sub create_glob_var {
my ($glob_var_str) = #_;
no strict 'refs';
$$glob_var_str = undef; # or whatever you want to set it to
}
create_glob_var("bah");
};
$bah = "blah";
Produces:
Variable "$bah" is not imported at /nfs/pdx/home/rbroger1/tmp2.pl line 12.
Global symbol "$bah" requires explicit package name at /nfs/pdx/home/rbroger1/tmp2.pl line 12.
Execution of /nfs/pdx/home/rbroger1/tmp2.pl aborted due to compilation errors.
NOTE I realize that using global variables causes ozone depletion and male pattern baldness. I'm trying to clean up some legacy code that is already completely infected with the use of global variables. One refactor at a time...
If you are trying to clean up old code, you can write a module which exports the required variable(s). Every time you feel the need to invoke create_glob_var, instead add a variable to this package and put that in the import list.
This will help you keep track of what is going on and how variables are being used.
package MyVars;
use strict; use warnings;
use Exporter 'import';
our($x, %y, #z);
our #EXPORT_OK = qw( $x %y #z );
The script:
#!/usr/bin/perl
use strict;use warnings;
use MyVars qw( $x %y #z );
$x = 'test';
%y = (a => 1, b => 2);
#z = qw( a b c);
use Data::Dumper;
print Dumper \($x, %y, #z);
Output:
$VAR1 = \'test';
$VAR2 = {
'a' => 1,
'b' => 2
};
$VAR3 = [
'a',
'b',
'c'
];
sub create_glob_var {
my ($glob_var_str) = #_;
no strict 'refs';
$$glob_var_str = undef; # or whatever you want to set it to
}
The no strict 'refs' is only necessary if use strict is in effect, which it always should be.
Addendum:
If you're asking if there's a way to write a subroutine create_glob_var such that the following code will succeed:
use strict;
create_glob_var("bar");
$bar = "whatever";
...then the answer is "No." However, Perl's vars pragma will do what you want:
use strict;
use vars qw($bar);
$bar = "whatever";
But this is kind of old-style Perl coding. Nowadays, one would typically do this:
use strict;
our $bar = "blah";
our can also just declare global variables that can be freely used later:
our ($foo, #bar, %baz);
# ...
$foo = 5;
#bar = (1, 2, 3);
%baz = (this => 'that');
Try looking at this question:
Does Perl have PHP-like dynamic variables?
In brief, it seems like you should be able to do $$glob_var_str = "whatever";
You would have to use an eval, but that's generally considered evil. Something like:
eval("$glob_var_str = \#_;");
EDIT
Just verified that you can only do this without the my and with no strict refs.
The vars pragma already does the heavy lifting for what you want, so put it to work:
#! /usr/bin/perl
use warnings;
use strict;
use vars;
BEGIN { vars->import(qw/ $bah /) }
$bah = "blah";
print $bah, "\n";
If you prefer to spell it create_glob_var, then use
#! /usr/bin/perl
use warnings;
use strict;
use vars;
sub create_glob_var { vars->import("\$$_[0]") }
BEGIN { create_glob_var "bah" }
$bah = "blah";
print $bah, "\n";
Either way, the output is
blah
I'm curious to know why you want to do it this way rather than declaring these variables with our. Yes, it may take a few iterations to catch them all, but these are short-term fixes anyway, right?
In general, you can use a variable as a variable name (see "Symbolic references" in perlref), but you really, really, really don't want to do that: enabling the strict 'refs' pragma disables this feature.
Rafael Garcia-Suarez showed great wisdom when he wrote, “I don't know what your original problem is, but I suggest to use a hash.”
See also:
Why it's stupid to 'use a variable as a variable name'
A More Direct Explanation of the Problem
What if I'm really careful?
Answer by Sinan Ünür is indeed the best. However, this picked my curiosity, so I did a bit of reading (perldoc perlmod)and learned about "package_name::" hash as a way to access the namespace of a package.
The following code adds a record to symbol table of main:: package:
use strict;
my $name = "blah";
my $var = "sss";
$main::{$name} = \$var;
print "$main::blah\n";
This prints "sss".
However, I had to add package name to print statement because "use strict" is still not fooled. I'll keep looking - use vars does not seem to work at the moment.