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

I'm a relative newbie to Perl, and I've been searching around the Monastery, the Llama book and the Camel book, and I'm not getting why my variables are going out of scope. I parse command line values and set a scalar variable defined in my Main (though Main is not named, just using the defaults). I then call a subroutine to open files, and other routines to process the files. I'm using 'our' in the sub where I reference the variable, but it is still out of scope sometimes.

I appreciate any help anyone can provide

Kelly

Here is a snippet from the file:

use strict; use warnings; use bytes; #... my $showPUV = 0; my $showPUVdesc = ""; # Call a sub, which calls a sub, etc... # The Main doesn't end until all files have been processed sub FilterMessage { $Line = $_[0]; our $showPUV; our $PUV; our $Report; our $EVENTNAME; our $EVENTTEXT; Clear_Arguments(); Parse_Messages(); ## IF we care about the PUV and it is NOT our PUV, don't show it # if (( defined $main::showPUV ) and ( defined $main::PUV )) { if ( $showPUV != 0 ) { ## This is undefined sometimes!! if ( $showPUV != $PUV ) { return $FALSE; } } # } ## else this test is OK, the line can be shown at this point if ( $Report eq "events" ) { if (( bytes::length $EVENTNAME > 0 ) or ( bytes::length $EVENTTEXT > 0 )) { return $TRUE; } } elsif ( $Report eq "comms" ) { ## need to do some more work here return $TRUE; } else { return $TRUE; } }

Replies are listed 'Best First'.
Re: problem with global variables going out of scope
by friedo (Prior) on Mar 28, 2006 at 18:19 UTC
    our $showPUV declares a package global, and my $showPUV declares a lexical variable. You've got two entirely different variables called $showPUV, which naturally leads to very confusing results. You certainly shouldn't be declaring package globals inside a subroutine; that's just begging for trouble.

    Check out Coping with Scoping.

Re: problem with global variables going out of scope
by Roy Johnson (Monsignor) on Mar 28, 2006 at 18:19 UTC
    You've got a $showPUV declared with my at the top, and one declared with our in the sub. Is that what you want? They are different variables, the former being declared lexically, and the latter being a global.

    You don't say specifically what variable goes out of scope when, so it's hard to tell you why it's happening.

    You might find Coping With Scoping to be enlightening.


    Caution: Contents may have been coded under pressure.
Re: problem with global variables going out of scope
by ikegami (Patriarch) on Mar 28, 2006 at 18:20 UTC
    ... my $showPUV = 0; ... sub FilterMessage { ... our $showPUV; ...

    Those are two different variables! The first is a lexical (my) variable, scoped to the file. The second is an alias to the package (our) variable $main::showPUV.

    Solution 1

    my $showPUV = 0; sub FilterMessage { ... if ( $showPUV ... ...

    Noone outside of this file can access $showPUV. FilterMessage can since it's in the same file, even if it's called from another file.

    Solution 2

    our $showPUV = 0; sub FilterMessage { ... if ( $showPUV ... ...

    Everyone can access $showPUV (altough other packages must use $main::showPUV). our $showPUV; is optional in FilterMessage, because the one at the top level is still in scope.

    Update: Clarified by adding "an alias to".

      Those are two different variables! The first is a lexical (my) variable, scoped to the file. The second is the package (our) variable $main::showPUV.

      Just a side note really, but our variables are somewhat lexically scoped.
      Actual package scoped variables are declared with use vars.

      Actually, they're lexically scoped symbol table entries, since this is perfectly valid:
      { our $var = 10; { package Other; our $var = 20; print "$var\n"; } print "$var\n"; } # no $var out here
      But I think it's best not to do these sort of things.


      acid06
      perl -e "print pack('h*', 16369646), scalar reverse $="

        I think of our as a lexically scoped directive similar to no strict 'vars'. The difference is that it only applies to the specified variables.

        You think of our as creating a lexically scoped variable which is aliased to a package variable.

        I don't agree with you. If the variable was lexically scoped, it wouldn't be possible to use it beyond the end of the lexical scope, as shown in the following code:

        { our $var = 20; } print("$var\n"); # 20

        Update: Cleaned up my post.

Re: problem with global variables going out of scope
by eff_i_g (Curate) on Mar 28, 2006 at 18:20 UTC
    I'm not sure how both showPUV's are supposed to interact. (Do you really want an our/local combination?) Have a look at Coping With Scoping.
Re: problem with global variables going out of scope
by Kelly Grant (Acolyte) on Mar 28, 2006 at 22:00 UTC
    Eureka!!! Thank you all so much. I want to learn Perl the right way, so I'm using strict and warnings, so when I got the message ""$showPUV" requires explicit package name" I started hunting, and found my(). I misunderstood the context, and then when I found our(), I thought they worked together, the my() to declare and the our() to reference. I changed my my()'s to our()'s and it works properly with no warnings!

    I'm going to like it here in the monastery.

    Thank you all for your prompt and correct replies, and for not being mean :-)

    Kelly