There is a same question on the forum.
How to share/export a global variable between two different perl scripts?
But, the suggestion for that was to use 'our' while declaration and then add 'require' in the other script. When I tried using it, the script fails saying 'Use of reserved word "our" is deprecated'.
Is there a different way to share parameter across different files. Thanks.
If you can't use the our keyword, then you have to fall back to simply using the variable without declaring it properly:
{
no strict;
$variable = "foo"; # implicitly a global
}
The syntax
$MyPackage::variable = "foo"; # uses the fully qualified name
should work too.
These will allow you to use the global, but will not scope the visibility of the name correctly.
However, you should absolutely and immediately upgrade that perl — it is a development release and not a regular release. The current release is perl5 v16.2.
Related
I am using strict and warning in my Perl scripts to be notified if I am using undeclared variables. Thus, the interpreter will warn that $foo is undeclared in the following scriptlet:
#!/usr/bin/perl
use warnings;
use strict;
$foo = 'bar';
print ($foo);
However, if I use an undeclared variable in another namespace, I am not warned. The following scriptlet runs without warning whatsoever.
#!/usr/bin/perl
use warnings;
use strict;
$BAR::foo = 'bar';
print ($BAR::foo);
Why is this difference?
Since I have lost quite some time figuring out exactly this problem, albeit in a much larger context, I am wondering if it is possible to make Perl me warn about using undeclared variables in other namespaces, too.
When you fully specify the namespace in which a variable belongs, perl assumes you know what you are doing. See perldoc strict:
strict vars
This generates a compile-time error if you access a variable that was neither explicitly declared (using any of my, our, state, or use vars) nor fully qualified.
I don't think there is a way to detect that you have specified a non-existent variable $BAR::foo. However, if the BAR package is under your control, you can avoid using package variables in the first place by mediating access to the state of foo using accessors, and hiding the variable from other modules.
The answer to problems created by using global variables is not to use global variables.
strict vars
This generates a compile-time error if you access a variable that was neither explicitly declared (using any of my, our, state, or use vars) nor fully qualified.
Perl "trusts" users when they use fully-qualified var names. I suspect it's to allow users to sets config variables in modules that don't use use strict;.
For example, let's look at the following snippet using Data::Dumper:
local $Data::Dumper::Useqq = 1;
print(Dumper($s));
Even long after use strict; was introduced, Data::Dumper didn't declare $Useqq. There wouldn't even have been a mechanism to do so before use strict;! So the above snippet would be using an undeclared variable. That means strict code would not have been able to use Data::Dumper in the above fashion if strict vars was enforced covered fully-qualified names.
It doesn't make sense to prevent strict code from using modules that aren't strict-safe, so strict vars doesn't cover fully-qualified names. These are rare enough and easily-identifiable enough to simply have programmers take more care when using them.
I am wondering if it is possible to make Perl me warn about using undeclared variables in other namespaces, too.
I don't know of existing solutions. It might be possible to hook into Perl to do that, but it would be very hard.
Keep in mind that Perl already warns you if you only use a package variable once, so this should help you catch typos.
Hi I have a perl script named main.pl. This perl script is calling three perl modules named sub1.pm, sub2.pm, and sub3.pm. sub.pm is returning three hashes which are being used in sub2.pm and sub3.pm. I am passing the hashes as input parameter to sub2 and sub3. Instead is there any way that I can declare the hashes globally so that it will be visible to these two perl modules?
When you declare non-global variables, it is done by putting "my" in front of it. i.e.:
my $local_variable = 4;
What you are wanting to do is replace the "my" with "our" and make sure it is placed outside of a subroutine. i.e.:
our $global_variable = 4;
If you wish to use it in other modules, you can add it by the following:
use vars qw($global_variable);
Now that I told you how to do it, I am going to tell you not to do it. It is strongly discouraged to use global variables. You should use local variables whenever you can. The reason for this is because if you are ever working on a larger project or a project with multiple coders, then you might find unknown errors as certain variables might not equal what you expect them to because they were changed elsewhere.
Every variable you declare in a module XY with
our $var;
our %hash;
or
use vars qw($var %hash);
is declared global and available as
$XY::var
%XY::hash;
in every other perl-module (if the module has already been used/required).
HTH
I am new to Perl and I have been following a book. All is well, except for whenever I try to initialize a variable as shown by the book, I am getting an error like below. Kindly tell me what should I do in order to avoid this error?
Code:
#!/usr/bin/perl -w
use 5.014;
use strict;
use utf8;
$radius = <STDIN>;
$circum;
if ($radius<0){
$circum = 0
} else{
$circum = 2*3.141*$radius;
}
print $circum."\n";
Errors:
Global symbol "$radius" requires explicit package name at ./example1 line 6.
Global symbol "$circum" requires explicit package name at ./example1 line 7.
Global symbol "$radius" requires explicit package name at ./example1 line 8.
Global symbol "$circum" requires explicit package name at ./example1 line 9.
Global symbol "$circum" requires explicit package name at ./example1 line 11.
Global symbol "$radius" requires explicit package name at ./example1 line 11.
Global symbol "$circum" requires explicit package name at ./example1 line 14.
Execution of ./example1 aborted due to compilation errors.
Also, I have read somewhere in the forums about 'our' and 'my' keywords. Using these seems to work. But, is it compulsory to use these keywords. If so, I think it is strange that the book did not include them.
The issue is the 'use strict' (which is actually a very good thing).
The result is that your variables need to be declared as follows:
my $radius = <STDIN>;
The 'my' keyword, there, makes the variable local to the current scope. And the 'use strict;' says you must declare all variables and specify their scope. The two typical ways you'd want to declare variables are:
my $localOnly;
our $shareableVariable;
Basically: use 'my' when you don't want anyone else to access the variable, and use 'our' when you want to allow external code to access or set the variable.
You've already got (and accepted) a answer to this question. But it might be worth raising another couple of points.
Firstly, if you don't understand a Perl error message, then it's often worth adding use diagnostics to your code. That will give you a more detailed explanation of the error. In this case, it would say:
(F) You've said "use strict" or "use strict vars", which indicates
that all variables must either be lexically scoped (using "my" or
"state"), declared beforehand using "our", or explicitly qualified to
say which package the global variable is in (using "::").
(Which, incidentally, shows the small omissions in the previous answer.)
Secondly, are you saying that your book recommends use strict but doesn't mention my? That sounds very strange. In any case, a Perl book that doesn't mention my is not a very good Perl book. Please tell us the title so that we can avoid it.
Short version
Is it possible to access variables from a module declared as our using unqualified names within the BEGIN code block, but using qualified names outside? In particular, can this be done without explicitely naming the package in the module file?
Example
Let demomod.pm be
use strict;
use warnings;
package demomod;
our $foo;
BEGIN { $foo = 42; }
1;
and demoscript.pl be
#!/usr/bin/perl -Tw
use strict;
use warnings;
BEGIN { #INC = ('.', #INC); }
use demomod;
print $demomod::foo."\n";
In this case, all names agree, and everything works as it should. Is there a way to omit the line package demomod; from the demomod.pm code and still let this work?
Motivation
The reason why I'm asking is because I encountered something along these lines during a recent upgrade of Foswiki. That software has a module Foswiki.pm which does not have a package line (EDIT: seems the package line only got lost in my local copy, for reasons unknown). It declares and initializes a variable $engine like in my example. There also is a CGI script called view which sets #INC and then does use Foswiki (); followed by $Foswiki::engine->run(). This last line always fails for me due to the variable not being initialized:
Can't call method "run" on an undefined value at …/view
In the BEGIN block of the module, $engine is set correctly but $Foswiki::engine apparently is not. So it looks like there were two variables here, one qualified and a different one unqualified.
All that code apparently works for others, and a previous version used to work for me as well, without a package line either. So while I try to understand how this broke, I also try to understand how this could work before, without that line in place. Is there some mechanism that would make this work?
If you have no package statement in your code then any package variables will be declared into the main package. So no, you cannot do what you describe.
If you look at line 2 of the Foswiki code that you linked, you will see that it does have a package statement.
Why does this print 42:
$answer = 42;
$variable = "answer";
print ${$variable} . "\n";
but this doesn't:
my $answer = 42;
my $variable = "answer";
print ${$variable} . "\n";
Only package variables (the kind declared in your first example) can be targeted via symbolic references. Lexical (my) variables, cannot be, which is why your second example fails.
See the excellent article Coping with Scoping for how the two separate variable systems in Perl operate. And see the also excellent Why it's stupid to use a variable variable name for why that's stupid. :)
Perl has two entirely separate but largely compatible variable systems, package variables, as in your first example, and lexical variables, as in the second. There are a few things that each can do but the other cant:
Package variables are the only ones that can be:
localized (with local)
used as the target for a symbolic reference (the reason the OP's second example doesnt work)
used as barewords (sub definitions, file handles)
used with typeglobs (because that's what the symbol really is under the hood)
Lexical variables are the only ones that can be closed over (used in a lexical closure).
Using strict would help by forcing you to declare package variables with our, making the difference clearer.
There are several times where symbolic references are useful in Perl, most center around manipulating the symbol table (like writing your own import in a module rather than using Exporter, monkey-patching modules at runtime, various other meta-programming tasks). All of these are advanced topics.
For other tasks, there is usually a better way to do it such as with a hash. The general rule of thumb is to always run under use warnings; use strict; unless you know there isn't any other way but to disable a portion of the pragma (such as using no strict 'refs'; in as small a scope as possible).
Symbolic references only work with package variables. The symbol table doesn't track lexical variables (which is the entire point of them being lexical :).
The problem is that you can't use a symbolic reference to refer to a lexical variable. In both examples ${$variable} is looking for $main::answer. In the first, $answer is a package global and short for $main::answer, so the reference finds it. In the second, $answer is a lexical variable and doesn't live in any package, so the reference can't find it.
More details in perlref under heading Symbolic references.