Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Is this a bug in Perl scope?

by Zarabozo (Acolyte)
on Jul 22, 2012 at 13:32 UTC ( #983064=perlquestion: print w/replies, xml ) Need Help??
Zarabozo has asked for the wisdom of the Perl Monks concerning the following question:

Hello,

I'm having an issue in a file that declares more than one package. It all boils down to the following example:
package one;
use strict;
use warnings;
my $var = 1;

package two;
use strict;
use warnings;
my $var = 5;

package main;
use strict;
use warnings;

print "$var\n";
Which gives the following warning an answer:
"my" variable $var masks earlier declaration in same scope at test.pl line 9.
5
1) Shouldn't the "package" mean a different scope and NOT produce the 'mask earlier declaration' warning?

2) Shouldn't the last line produce an error instead of printing "5" since $var was never defined on 'main' and all packages use strict?

I tried this on Perl 5.010 and Perl 5.014 with the same result.

This really scares me. :-|

Francisco

Replies are listed 'Best First'.
Re: Is this a bug in Perl scope?
by Corion (Pope) on Jul 22, 2012 at 13:35 UTC

    No. package only declares a new package, it does not end the lexical scope of the previous package. The $var you use after the package main statement is the lexical $var that you declared after the package two; statement.

      Ok, then, if the scope is the same:

      1) Why the variable doesn't really get redefined?
      2) Why 'my' produces a warning and 'our' doesn't? (if you use 'our' 2 times in the same package for the same variable, you DO get a warning)

      On the following code, you get the 'mask earlier declaration' warning twice. Yet, it's not the same variable since each one keeps their current value. If you change "my" for "our", you don't get any warning about redefining the same var:
      package one;
      use strict;
      use warnings;
      my $var = 1;
      sub tell {
      	print "$var\n";
      }
      
      package two;
      use strict;
      use warnings;
      my $var = 5;
      sub tell {
      	print "$var\n";
      }
      
      package main;
      use strict;
      use warnings;
      my $var = '20';
      sub tell {
      	print "$var\n";
      }
      
      one::tell();
      two::tell();
      main::tell();
      
      Produces the following output:
      "my" variable $var masks earlier declaration in same scope at test.pl line 12.
      "my" variable $var masks earlier declaration in same scope at test.pl line 20.
      1
      5
      20
      

        our and my are very different things. our creates an alias for a global variable. my creates a name and a value.

        The only thing the two have in common is that the alias created by our and the name created by my are valid within the current scope.

        As Perl assumes that you don't want to shadow the name created by a my statement, because it likely is the only way to get at its associated value, it warns you about this.

        I don't know why our doesn't always warn, but that may be because I don't use our. I prefer the vars pragma, which only creates the values within the package, which seems to me what you expect.

        I think the main issue for you is that package does not end a previous lexical scope. Some people try to manage that by using the following syntax:

        package foo { # this block provides lexical scope for package foo ... }; package bar {# this block provides lexical scope for package bar ... };

        I don't see much use in that because my packages are either so large that they live in separate files or are so tiny that they only consist of configuration data masquerading as code. In neither case, lexical scope plays much of a role on the package scope.

        By the way (though not a part of your stated problem), tell is a native function name... and thus a poor choice for the name of a sub.

        perdoc -f tell will give you the details; in short, tell can help you find your location in a filehandle.

Re: Is this a bug in Perl scope?
by trwww (Priest) on Jul 23, 2012 at 21:29 UTC

    This behavior is documented very clearly:

    perldoc -f my A "my" declares the listed variables to be local (lexically) to the enclosing block, file, or "eval".

    There no such thing as a "package scope". To do what you want you'd have to use blocks:

    $ perl use strict; use warnings; { package one; my $var = 1; } { package two; my $var = 5; } package main; print "$var\n"; Global symbol "$var" requires explicit package name at - line 16. Execution of - aborted due to compilation errors.

    Also, FYI warnings and strict are filescoped also if they aren't in a more specific container.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://983064]
Approved by Corion
Front-paged by kcott
help
Chatterbox?
[perldigious]: Hmm, thanks Lotus1... perldigious scribbles note to buy lots of opossums as "pets" in the future to hang around outside his property. :-P
[1nickt]: You must twist and pull! If you burn, use tea tree oil etc, the tick barfs (inside your blood vessel) and you get all the loevely bacteria in his gut transferred to yours.
[1nickt]: tweesers work just fine
[hippo]: Hope everyone else is enjoying their lunch too.
[1nickt]: However, note that it takes between 2 and 4 hours for a tick to be able to start transmitting bacteria. So even if it has burrowed in and started eating, if you get it soon you should be OK.
[perldigious]: 1nickt: No more red meat! It would be more humane to just kill you, wouldn't it! :-)
[1nickt]: Just don't make it barf.
[1nickt]: perldigious that's exactly what my stepson says.
[1nickt]: the tick that can make you a vegetarian
[perldigious]: Your Mother: Yeah, I have a tool for ticks that I use (mostly on my dogs thankfully), but it's just a cheapo one I got from my vets office... it works pretty good though.

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (14)
As of 2017-05-24 13:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?