views:

176

answers:

3

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?'

+4  A: 

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 http://stackoverflow.com/questions/845060

Michael Carman
+8  A: 

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 http://stackoverflow.com/questions/820348/why-are-the-number-of-pages-in-a-word-document-different-in-perl-and-word-vba/821569#821569

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.

Sinan Ünür
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. :)
Dave Sherohman
+5  A: 

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).

Greg Bacon
+1 and accepted - this answer best answers my questions. Thanks!
romandas