our $gotcha

brian_d_foy on 2008-02-14T20:11:00

On the first morning of the 10th German Perl Workshop Max did a tutorial on Advanced Perl during which someone asked about the difference between our and use vars. Max didn't know the answer offhand (and being smart, doesn't need to pretend to be by pretending to know the answer), and I had to scratch my head a bit when Jürgen told me about it (I'd been in the other tutorial), so Jürgen asked if I could do a lightning talk to explain it. I said yes (which seemed to be consistent with a question at breakfast - Jonathan asked "are you speaking this year?" and I replied "not yet").

However, today it turned out that it is a good thing that I am a virtuously lazy programmer and hadn't written any slides, as Steffen Ullrich did an excellent talk on Perl Gotchas which had an example of code which explained it much better than I could. Specifically, consider the following:

!/usr/bin/perl -w

use strict;

package awk;

# ...

package urkk;
our @ISA = 'awk';

# ...

package rakkk;
our @ISA = 'urkk';

# ...

package owww;
@ISA = 'rakkk';

# ...

1;

All nicely strict clean:

$ perl -Mawk -e0

but nevertheless buggy. Why? Because the inheritance isn't set up correctly:

$ perl -Mawk -wle 'print @owww::ISA'

$ perl -Mawk -le 'print @rakkk::ISA'
rakkk
$

Erk! How did that happen? It's because the our was missed from the last assignment. It should read:

package owww; our @ISA = 'rakkk';

But without that our, that last assignment is still to the variable @rakkk::ISA , not @owww::ISA, because our actually creates a lexical alias to the global variable, a lexical that is still in scope for the rest of the file.

Whoops! Gotcha!


Another gotcha for you

btilly on 2008-02-14T17:51:52


$ perl -wle 'package foo; our $_; print map {$_} 1..5'
Use of uninitialized value in print at -e line 1.
Use of uninitialized value in print at -e line 1.
Use of uninitialized value in print at -e line 1.
Use of uninitialized value in print at -e line 1.
Use of uninitialized value in print at -e line 1.

What happened? Well $_ is supposed to be $main::_. But after the our, $_ is now looking at $foo::_ while map still populates $main::_.

You may find http://www.perlmonks.org/?node_id=48379 to be of interest as well.

Sooo....

Alias on 2008-02-15T01:05:55

So it would be a flaw in a Perl file, if it contains multiple packages, with our statements in them... or at least a critic-worthy warning?

Re:Sooo....

chromatic on 2008-02-15T01:19:04

File-scoped our variables could be a problem. Block-scoped our variables are less troublesome.

Yet another gotcha

Maddingue on 2008-02-15T07:55:32

Another small problem with our variables is that they take twice the memory of lexical variables or plain global.

Re:Yet another gotcha

kwilliams on 2008-02-17T14:24:09

That comment is a bit misleading; if you have a 1000-byte string in an our variable it's not suddenly going to consume 2000 bytes. It would be more accurate to say they take twice the overhead.

Lexical alias

Juerd on 2008-02-17T14:18:03

So in short: "our" creates a lexically scoped alias for a package global variable. And lexical scope itself has nothing to do with packages, but with curlies and files.