Take the 2-minute tour ×

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?

share|improve this question
I devote an entire chapter in Mastering Perl to your options (heh) here. :) –  brian d foy Mar 7 '12 at 4:40
the shebang line is wrong; it should be #!/usr/bin/env perl then use strict; on a new line for maximum portableness –  Good Person Oct 21 '13 at 0:01
add comment

3 Answers

up vote 4 down vote accepted

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.

share|improve this answer
Good catch. I didn't notice "-s" in my rush. +1 –  DVK Mar 7 '12 at 3:52
Re: "I doubt it is compatible with use strict": It is. See my answer below for how. :-) –  ruakh Mar 7 '12 at 3:55
Sheer luck, I'm dead on my feet. =) –  TLP Mar 7 '12 at 3:56
@ruakh Good point, added. –  TLP Mar 7 '12 at 4:02
If you are going to discard -s, the solution isn't to make lexical variables (which are really just file scoped globals in this case, which might as well be global variables in a single file program). Now you have to parse the options yourself. You could use one of the Getopt modules, but -s is often handy when you don't want to go that far. –  brian d foy Mar 7 '12 at 4:39
show 1 more comment

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.

share|improve this answer
our ($x, $y) should work too, I believe (haven't tested) –  derobert Mar 7 '12 at 3:57
@derobert: You're quite right; I have tested, and have shamelessly stolen that for my answer. Thanks! :-) –  ruakh Mar 7 '12 at 4:02
add comment

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

  1. a package-scoped global that is prohibited from being used under strict ("Global symbol "$x" requires explicit package")

  2. 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.

share|improve this answer
add comment

Your Answer


