SPUG: Predeclaring packages

Ronald J Kimball rjk-spug at tamias.net
Fri Jan 2 20:42:04 PST 2009


On Fri, Jan 02, 2009 at 08:11:22PM -0800, DeRykus, Charles E wrote:
>  
> > I did some more experimentation, and I think I know what was confusing me. 
> > Maybe you can confirm this: the scoping for an 'our' statement occurs during 
> > compiling, but actual variable assignments occur during runtime.

Yes, that is basically correct.


> > use strict;
> > use warnings;
> 
> > Hello::sayHi();
> > exit(0);
> 
> > package Hello;
> > {
> 
> > our $greeting = 'Hello there';
> 
> > sub sayHi { print $greeting . "\n" }
> 
> > }
> 
> 
> Um, it's not a compilation vs. runtime issue: "our" just exposes a value
> for a global variable within a specific scope. Since the <our $greeting =
> 'Hello there'> in package Hello is not in scope when Hello::sayHi() is
> called, it's undefined. That's why it only works if you declare
> <$Hello::greeting = 'Hello there'> before the call to Hello::sayHi. Note
> though a deckaration such as <"our $greeting = "Hello there'> just prior
> to Hello::sayHI wouldn't work because the scope of 'our' won't extend
> into package Hello. And that's why I suggested assigning the global
> variable to an "our" variable to avoid tediously needing a package
> qualifier for $greeting when used in other scopes.

In fact, it /is/ a compilation vs. runtime issue.  The <our $greeting =
'Hello there'> in package Hello is in the same scope as the sayHi
subroutine.  If it were a scoping issue, then there would have been an
error: Global symbol "$greeting" requires explicit package name.

The reason the code results in an uninitialized value warning is that the
assignment has not been executed yet when Hello:sayHi() is called.

One simple way to resolve this - and to demonstrate that is a compilation
vs. runtime issue - is to use a BEGIN or INIT block to ensure
that the assignment is executed before runtime.  (BEGIN blocks are
executed immediately during compilation; INIT blocks are executed between
compilation and runtime.)

use strict;
use warnings;

Hello::sayHi();
exit(0);

package Hello;
INIT {
  
our $greeting = 'Hello there';
  
sub sayHi { print $greeting . "\n" }

} 


Ronald


More information about the spug-list mailing list