Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Journal of nicholas (3034)

Thursday February 14, 2008
11:41 AM

our $gotcha

[ #35654 ]

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!

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.

  • $ 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 [perlmonks.org] to be of interest as wel
  • 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?
    • File-scoped our variables could be a problem. Block-scoped our variables are less troublesome.

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

    --
    Close the world. txEn eht nepO
    • 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.
  • 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.