When should you use a package variable vs a lexical variable (and what's the difference)?
Asked Answered
F

3

5

I'm looking at some older Perl code on Perl Monks to figure out programming with Win32::OLE and MS Word. Scattered throughout the code are variables with names like $MS::Word and the like, without a 'my' included in their declaration. After reading a bit on Google, I understand that these are called 'package variables' versus 'lexical variables' declared using my.

My first question is 'What are package variables good for?'. I (think) I understand what lexical variables are, but I don't understand the purpose of package variables or how their use differs from lexicals, so my second question would be, 'What is the difference between lexical and package variables?'

Filum answered 19/6, 2009 at 19:17 Comment(3)
As an aside, someone else who looked at that code called it 'ugly'. I'm not sure how to tell if it's ugly or not. Anyone care to enlighten me? :)Filum
In part it's ugly because it's doing OLE. That's never pretty. My main complaint with the code is abuse of package variables. It uses them extensively but never declares a package. That's an indication that the author didn't really understand the tools he was using.Arioso
OLE is never pretty but Perl code does not have to be this ugly. I am still having flashbacks of the time when I had to deal with some Cobol code 15 years ago.Sisco
K
8

A package variable lives in a symbol table, so given its name, it's possible to read or modify it from any other package or scope. A lexical variable's scope is determined by the program text. The section "Private Variables via my()" in the perlsub manpage gives more detail about defining lexicals.

Say we have the following MyModule.pm:

package MyModule;

# these are package variables
our $Name;
$MyModule::calls = "I do not think it means what you think it means.";

# this is a lexical variable
my $calls = 0;

sub say_hello {
  ++$calls;

  print "Hello, $Name!\n";
}

sub num_greetings {
  $calls;
}

1;

Notice that it contains a package $calls and a lexical $calls. Anyone can get to the former, but the module controls access to the latter:

#! /usr/bin/perl

use warnings;
use strict;

use MyModule;

foreach my $name (qw/ Larry Curly Moe Shemp /) {
  $MyModule::Name = $name;
  MyModule::say_hello;
}

print MyModule::num_greetings, "\n";

print "calls = $MyModule::calls\n";

The program's output is

Hello, Larry!
Hello, Curly!
Hello, Moe!
Hello, Shemp!
4
calls = I do not think it means what you think it means.

As you can see, package variables are globals, so all the usual gotchas and advice against apply. Unless explicitly provided access, it's impossible for code outside the MyModule package to access its lexical $calls.

The rule of thumb is you very nearly always want to use lexicals. Perl Best Practices by Damian Conway is direct: "Never make variables part of a module's interface" (emphasis in original).

Keaton answered 19/6, 2009 at 20:10 Comment(1)
+1 and accepted - this answer best answers my questions. Thanks!Filum
B
9

You should read Coping with Scoping by MJD.

perldoc perlmod would also be useful reading.

The code is out of this world ugly. It tramples on all sorts of namespaces without a concern in the world just because the author seems to think $author::email is cool.

A better way would have been to use a hash:

my %author = (
   email => '[email protected]',
   ...
);

Trampling all over the symbol table is not necessary.

I do have a few Win32::OLE examples: http://www.unur.com/comp/ which are no works of art but I believe are improvements on this style. See also Why are the number of pages in a Word document different in Perl and Word VBA?

I am going to rant a little:

@pgm::runtime_args = @ARGV ;

So, we give up on the standard @ARGV array to trample on the pgm namespace. Not only that, every Perl programmer knows what @ARGV is. In any case, @pgm::runtime_args is not used again in the script.

$pgm::maxargs = $#pgm::runtime_args + 1 ;

Of course @pgm::runtime_args in scalar context would give us the number of elements in that array. I have no idea why $pgm::maxargs might be needed, but if it were, then this line should have been:

$pgm::maxargs = @pgm::runtime_args;

I am not going quote more of this stuff. I guess this is what happens when Cobol programmers try to write Perl.

$program::copyright = "Copyright (c) 02002 - Kenneth Tomiak : All rights reserved.";

I am glad he allocated five digits for the year. Ya never know!

PS: I believe my excerpts constitute fair use.

Bordure answered 19/6, 2009 at 19:31 Comment(1)
Ah, but the leading 0 indicates that it's an octal number - apparently, the copyright date is the year 1026, so the code should be public domain by now. :)Fortnightly
K
8

A package variable lives in a symbol table, so given its name, it's possible to read or modify it from any other package or scope. A lexical variable's scope is determined by the program text. The section "Private Variables via my()" in the perlsub manpage gives more detail about defining lexicals.

Say we have the following MyModule.pm:

package MyModule;

# these are package variables
our $Name;
$MyModule::calls = "I do not think it means what you think it means.";

# this is a lexical variable
my $calls = 0;

sub say_hello {
  ++$calls;

  print "Hello, $Name!\n";
}

sub num_greetings {
  $calls;
}

1;

Notice that it contains a package $calls and a lexical $calls. Anyone can get to the former, but the module controls access to the latter:

#! /usr/bin/perl

use warnings;
use strict;

use MyModule;

foreach my $name (qw/ Larry Curly Moe Shemp /) {
  $MyModule::Name = $name;
  MyModule::say_hello;
}

print MyModule::num_greetings, "\n";

print "calls = $MyModule::calls\n";

The program's output is

Hello, Larry!
Hello, Curly!
Hello, Moe!
Hello, Shemp!
4
calls = I do not think it means what you think it means.

As you can see, package variables are globals, so all the usual gotchas and advice against apply. Unless explicitly provided access, it's impossible for code outside the MyModule package to access its lexical $calls.

The rule of thumb is you very nearly always want to use lexicals. Perl Best Practices by Damian Conway is direct: "Never make variables part of a module's interface" (emphasis in original).

Keaton answered 19/6, 2009 at 20:10 Comment(1)
+1 and accepted - this answer best answers my questions. Thanks!Filum
A
5

Package variables are global variables; they're visible everywhere in the entire program (even other modules). They're useful when you want or need that level of visibility and/or external influence. For example the Text::Wrap module uses them to allow a single configuration point for the number of columns at which to wrap text. Futhermore, package variables allow you to use something called "dynamic scoping" -- but that's a somewhat advanced and slightly esoteric concept.

For your second question, see What is the difference between my and our in Perl?

Arioso answered 19/6, 2009 at 19:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.