0

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
Craig Treptow
  • 834
  • 7
  • 19
seeram
  • 11
  • 3

4 Answers4

4

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

pavel
  • 3,488
  • 1
  • 20
  • 20
2

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.

dan1111
  • 6,576
  • 2
  • 18
  • 29
0

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

Jon
  • 188
  • 1
  • 8
  • i dont want any code change suggestion. here i am trying to understand the behaviour. so can you please tell me (if you know) why it prints 12 but not 10, when we call the function. – seeram Aug 09 '12 at 11:39
-1

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();

orhanhenrik
  • 1,407
  • 8
  • 11
  • i dont want any code change suggestion. here i am trying to understand the behaviour. so can you please tell me (if you know) why it prints 12 but not 10, when we call the function. – seeram Aug 09 '12 at 11:45
  • 1
    Don't call subroutines like: `&display`! Unless you know what is means and what its side effects are! – pavel Aug 09 '12 at 11:56
  • You can't expect a logic outout when the code has a lot of errors..The subroutine thinks `my $p=12` is the variable it's supposed to print, and because the first time you call the subroutine `my $p=12` is not yet declared, it prints nothing – orhanhenrik Aug 09 '12 at 12:01
  • @seeram If you want to learn programming, don;t bother about undefined behaviour. Learn the basics, then fix the errors in your code and go on. After you do that a million times, while studying the language itself deeper and deeper in the meantime, you'll get to understand the errorneous behaviours as well. (Maybe not all of them, some of those are really mysterious.) – Alois Mahdal Aug 09 '12 at 12:12
  • @Alois, I think that trying to understand the behavior in a case like this is a very useful and informative exercise. Yes, it is worth pointing out the problems with his code, but it is also worth understanding what goes on behind the scenes that produces such an unexpected result. 'Unexpected' but not 'undefined', as in this case the output is the defined behavior of Perl. – dan1111 Aug 10 '12 at 08:30
  • @dan1111 My point wasn't to discourage OP from srudying his errors, I just wanted to remind the it's sometimes better to let the correct prectices get into your bloodstream before diving too deep... However, you are more right than me, especially in point that this *is* defined. +1 and thanks for your answer :) – Alois Mahdal Aug 10 '12 at 14:23