http://www.perlmonks.org?node_id=1067820

rongrw has asked for the wisdom of the Perl Monks concerning the following question:

Dear Perl Monks,

My question is about the scope of package variables. When I run the code listed at the bottom of this post, the following is displayed:

Use of uninitialized value $sv_a in concatenation (.) or string at ./s +cope_t.pl line 15. DumpValue: sv_a ...
I'm a little confused about this, because my understanding of package variables is that they are in scope within subsequent subroutine or method definitions. Why is perl interpreting $sv_a as having an uninitialized value, when it clearly is initialized inside the package?

I'm using perl 5.10.1. If anyone could advise where I'm going wrong, that would be much appreciated. Now for the code ...

#!/usr/local/bin/perl use 5.010; use strict; use warnings; MainFunction: { my $t_obj = ScopeTest->new(); $t_obj->dump_sv(); } package ScopeTest; my $sv_a = "scalar variable A"; sub dump_sv { print("DumpValue: sv_a ... $sv_a\n"); } sub new { my $obj_hv = {}; bless($obj_hv, $_[0]); } 1;

Cheers, Ron.

Replies are listed 'Best First'.
Re: Scope of package variables
by tobyink (Canon) on Dec 19, 2013 at 14:22 UTC

    It is in scope. It's just currently set to undef. You're executing this line:

    $t_obj->dump_sv();

    ... before you execute this line:

    my $sv_a = "scalar variable A";

    So $sv_a has no value yet.

    This, for example, works:

    #!/usr/local/bin/perl use 5.010; use strict; use warnings; my $sv_a; MainFunction: { $sv_a = "scalar variable A"; my $t_obj = ScopeTest->new(); $t_obj->dump_sv(); } package ScopeTest; sub dump_sv { print("DumpValue: sv_a ... $sv_a\n"); } sub new { my $obj_hv = {}; bless($obj_hv, $_[0]); } 1;

    Being pedantic, variables declared with my are not "package variables", but "lexical variables". Package variables are those declared with our (in fact, these are lexical aliases to package variables), or those that are not declared at all.

    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
      Thank you Monks, for all your great suggestions to my recent question. The approach I took was to move the MainFunction block below the definition of the package ScopeTest. This solved the problem nicely. I've added the final code to the bottom of this post.

      tobyink clarified the difference between lexical variables and package variables, which I think I now understand. In the code below, I added a second print statement in MainFunction{}.

      print("DumpValue: sv_a ... $ScopeTest::sv_a\n");

      Now, if the variable $sv_a is declared as my $sv_a = ..., then the message "Use of uninitialized value $ScopeTest::sv_a ..." is displayed and the program fails. But, if the variable $sv_a is declared as our $sv_a = ..., then the program runs just fine without any errors.

      The final working code with $sv_a declared as a package variable is now:

      #!/usr/local/bin/perl use 5.010; use strict; use warnings; package ScopeTest; our $sv_a = "scalar variable A"; sub dump_sv { print("DumpValue: sv_a ... $sv_a\n"); } sub new { my $obj_hv = {}; bless($obj_hv, $_[0]); } package main; MainFunction: { my $t_obj = ScopeTest->new(); $t_obj->dump_sv(); print("DumpValue: sv_a ... $ScopeTest::sv_a\n"); }
Re: Scope of package variables
by tangent (Parson) on Dec 19, 2013 at 14:29 UTC
    If you put ScopeTest in a separate file and then use ScopeTest; it will work as you expect.
Re: Scope of package variables
by NetWallah (Canon) on Dec 19, 2013 at 14:40 UTC
    As an alternative to tangent's solution, you could put the declaration and contents of "package ScoptTest" inside a BEGIN{} block.

                 When in doubt, mumble; when in trouble, delegate; when in charge, ponder. -- James H. Boren

Re: Scope of package variables
by Laurent_R (Canon) on Dec 19, 2013 at 18:11 UTC
    ... Or you could add to your package a subroutine to initialize $sv_a at the beginning of your program.