Reputation: 969
Why is it that my code is not working after I added use strict; use warnings;
? Is there a way to make it work?
Previously, the working code is:
#!/usr/bin/perl -s
print "x: $x\n";
print "y: $y\n";
The command that I ran is perl -s test.pl -x="hello" -y="world"
. The output is:
x: hello
y: world
However, after I added use strict; use warnings;
, I got the following errors:
Variable "$x" is not imported at test.pl line 4.
Variable "$y" is not imported at test.pl line 5.
Global symbol "$x" requires explicit package name at test.pl line 4.
Global symbol "$y" requires explicit package name at test.pl line 5.
Execution of test.pl aborted due to compilation errors.
I know I need to declare my $x
and my $y
to fix the 3rd and 4th error. But what does the first 2 errors mean and how do I overcome it?
Upvotes: 8
Views: 8051
Reputation: 183251
Actually, declaring these variables as lexical (my
) variables will not help, because it's too "late": the -s
switch will already have set them. It sets the global (package) variables (in your case, $main::x
and $main::y
, or — as a special shorthand — $::x
and $::y
). If you don't want to have to refer to them using their package-qualified names, then you can use an our
declaration to indicate that the bare names $x
and $y
refer to the $x
and $y
in the current package:
our ($x, $y);
print "x: $x\n";
print "y: $y\n";
(Hat-tip to derobert for pointing out that you can use our
for this.)
Alternatively, you can copy the global variables into identically-named lexical variables:
my ($x, $y) = ($::x, $::y);
print "x: $x\n";
print "y: $y\n";
This will take care of both sets of diagnostics.
Upvotes: 9
Reputation: 67900
You are using a a rudimentary switch parser perl -s
, which uses global variables. To make it work with use strict
you need to refer to the globals: $main::x
as ruakh pointed out.
But even so, lexical variables (declared with my
) are preferable in just about all cases. Just do:
use strict;
use warnings;
my ($x, $y) = @ARGV;
print "x: $x\n";
print "y: $y\n";
And use with:
perl test.pl hello world
For a more detailed and switch like handling, check out the Getopt::Long module.
Upvotes: 4
Reputation: 129383
To understand what ANY Perl error/warning means, you can refer to perldiag
.
Specifically, for "is not imported", it says:
Variable "%s" is not imported%s
(W misc) With "use strict" in effect, you referred to a global variable that you apparently thought was imported from another module, because something else of the same name (usually a subroutine) is exported by that module. It usually means you put the wrong funny character on the front of your variable.
Basically, Perl made 2 distinct guesses about your un-declared identifyer $x
- it was either
a package-scoped global that is prohibited from being used under strict
("Global symbol "$x" requires explicit package")
or it was an attempt to use another package's variable that ought to have been imported but wasn't ("Variable "$x" is not imported").
Perl can not tell WHICH of the two theories are correct, so spat out both possibilities. The latter error (Global symbol "$x" requires explicit package name) was the correct one in this case - it WAS a global variable in your original pre-strict code.
Upvotes: 2