Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 829
romandas Avatar asked Jun 19 '09 19:06

romandas


2 Answers

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.

like image 193
Sinan Ünür Avatar answered Oct 10 '22 09:10

Sinan Ünür


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

like image 37
Greg Bacon Avatar answered Oct 10 '22 09:10

Greg Bacon