SPUG: Confusing behaivior with exported variables

Jacinta Richardson jarich at perltraining.com.au
Tue Mar 24 15:37:29 PDT 2009


Mark Mertel wrote:

> *It does work:*
> **
>  
> *package Foo;*
> *my $bar = "foo bar\n";*
> *1;*
> *...*
> ** 
> *use Foo;*
> *use strict;*
> ** 
> *print $Foo::bar; # prints 'foo bar'*
> ** 
> *print $bar; # should throw an error*
> 
> 
> I'll leave the in-depth explaining of the differences between "lexical
> variables" and "package globals" to other sources, but those are the two
> choices. :)

Technically you're both wrong.  Declaring variables with "our" does not make
them global.  It makes them package variables.  However, as Mark has hopefully
discovered now, declaring variables with *my* does not cause them to behave the
way he thought they did.

Lexical variables (those declared with my) exist for their smallest enclosing
scope.  This is either a block (as defined by curly brackets) or the file
they're declared in.  Thus:

	#!/usr/bin/perl -w
	use strict;
	my $foo;	    # Visible to the whole file

	while(<>) {
		my $bar;    # Visible only to the end of the while block
	}

Variables declared with my cannot ever be seen outside the file they are
declared in.

Package variables (those declared with our, or created when you mention a
variable without strict turned on) are visible from the point they are created
to the end of their file; and are accessible to other files as well (when
exported or when their full name is used):

	# Foo.pm
	package Foo;
	use strict;
	my $foo = "This is lexical";
	our $bar = "This is a package variable";

	# test.pl
	#!/usr/bin/perl -w
	use strict;
	use Foo;

	print "foo: $Foo::foo\n"; # foo: <uninitialised> (looks for package var)
	print "bar: $Foo::bar\n"; # bar: This is a package variable
	
of course, if you stick them both in the *same* file, you can see the lexical
variable:

	package Foo;
	use strict;
	my $foo = "This is lexical";
	our $bar = "This is a package variable";

	package main;
	use strict;
	use Foo;

	print "foo: $foo\n";      # foo: This is lexical
	print "bar: $bar\n";      # bar: This is a package variable
	print "foo: $Foo::foo\n"; # foo: <uninitialised>
	print "bar: $Foo::bar\n"; # bar: This is a package variable

because the scope of these variables is their smallest enclosing block or file.
 Packages do not denote blocks.  To get the "correct" effect you'd need more braces:

	{
		package Foo;
		use strict;
		my $foo = "This is lexical";
		our $bar = "This is a package variable";
	}
	package main;
	use strict;
	use Foo;

	print "foo: $Foo::foo\n";  # foo: <uninitialised>
	print "bar: $Foo::bar\n";  # bar: This is a package variable

Perl's true globals are its special variables, which are visible and changable
by everything - whether you want them to be or not.  Package variables are often
called globals, but they're not real globals in the computer science sense.
Close enough though.

	J

-- 
   ("`-''-/").___..--''"`-._          |  Jacinta Richardson         |
    `6_ 6  )   `-.  (     ).`-.__.`)  |  Perl Training Australia    |
    (_Y_.)'  ._   )  `._ `. ``-..-'   |      +61 3 9354 6001        |
  _..`--'_..-_/  /--'_.' ,'           | contact at perltraining.com.au |
 (il),-''  (li),'  ((!.-'             |   www.perltraining.com.au   |


More information about the spug-list mailing list