in reply to Is this a bug in Perl scope?

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.

Replies are listed 'Best First'.
Re^2: Is this a bug in Perl scope?
by Zarabozo (Sexton) on Jul 22, 2012 at 13:53 UTC
    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.

        This syntax:

        package foo { ... }

        ... only works in Perl 5.14 and above. In earlier versions of Perl, you'll need a semicolon before the block...

        package foo; { ... }

        Though it is in my experience more conventional to put the package declaration inside the block itself:

        { package foo; ... }

        Update: as per AnomalousMonk's post below, this latter style has the added advantage that the package declaration itself is lexically scoped, so after perl parses the closing curly brace it puts you back into the main package. I knew that already really. ;-) The new Perl 5.14 syntax also does this, but the middle example does not.

        perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
      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.