Question

The below code gives some strange output. Can any one explain the problem?

use warnings;
my $P = 10;
print "My Var: $P\n";
display();

my $P = 12;
display();

sub display()
{
    print "My Var: $P\n";
}

output:

My Var: 10
My Var:
My Var: 12
Was it helpful?

Solution

First of all, in Perl you are not required to define a subroutine before calling it; it would be a better practice to do so; hence the warning your code produces. However, there is nothing technically wrong in this regard; nor is this warning relevant to your problem.

I believe the answer is indeed in your two declarations of the same variable with "my", coupled with the specific behavior of the Perl interpreter. Here is the explanation of this warning from perldiag:

``my'' variable %s masks earlier declaration in same scope (S) A lexical variable has been redeclared in the same scope, effectively eliminating all access to the previous instance. This is almost always a typographical error. Note that the earlier variable will still exist until the end of the scope or until all closure referents to it are destroyed.

When your print statement happens, only the first declaration of $P has been processed by the interpreter, thus it prints 10, as you would expect.

However, when you call the sub, Perl goes to look for the subroutine definition. It also has to find all of the other variable declarations preceding it, so that the sub can have access to lexical variables; it finds the second declaration, and thus your first $P is overwritten with a new $P. However, since this new $P hasn't been set to anything yet in your program, it is undefined.

OTHER TIPS

You should give the complete output of your script:

"my" variable $P masks earlier declaration in same scope at P line 6.
main::display() called too early to check prototype at P line 4.
main::display() called too early to check prototype at P line 7.
My Var: 10
Use of uninitialized value in concatenation (.) or string at P line 11.
My Var:
My Var: 12

and read it... The answer is in the warning...
and if you add use strict; in the start of your script, you would get the additional warning:

main::display() called too early to check prototype at P line 5.
main::display() called too early to check prototype at P line 8.

Which means that you call a subroutine WITH a prototype (in this case ()) before declaring it...
So declare the subroutine first or, better yet, drop the prototype.

change your code to:

use strict;
use warnings;

my $P = 10;
print "My Var: $P\n";

display();

$P = 12;

display();

sub display
{
    print "My Var: $P\n";
}

And it works as you would expect.
(but better use $P as an argument for the subroutine...)

"my $P" declares the variable. You do that twice, which you also should get an error for. change "my $P = 12;" to "$P = 12;" and you'll get what you want.

I would recommend you to read up a bit on perl (look at "perldoc perl" and "perldoc perlintro", or http://www.perl.org/learn.html)

my $P = 12; You already declared $P(my $P = 10;) above, and should not do this again, remove the my,
display(); call the subroutine like this: &display();

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top