12.4. Making Variables Private to a ModuleProblemYou want to make a variable or function private to a package. SolutionYou can't. But you can make them private to the file that the module sits in, which usually suffices. DiscussionRemember that a package is just a way of grouping variables and functions together, conferring no privacy. Anything in a package is by definition global and accessible from anywhere. Packages only group; they don't hide. For privacy, only lexical variables will do. A module is implemented in a Module.pm , with all its globals in the package named Module. Because that whole file is by definition a scope and lexicals are private to a scope, creating file-scoped lexicals is effectively the same thing as a module-private variable. If you alternate packages within a scope, though, you may be surprised that the scope's lexicals are visible no matter where you are. That's because a package statement only sets a different prefix for a global identifier. package Alpha; my $aa = 10; $x = "azure"; package Beta; my $bb = 20; $x = "blue"; package main; print "$aa, $bb, $x, $Alpha::x, $Beta::x\n"; 10, 20, , azure, blue
Was that the output you expected? The two lexicals,
So, packages can't have privacy - but modules can because they're in a file, which is always its own scope. Here's a simple module, placed in the file
Flipper.pm
, that exports two functions, # Flipper.pm package Flipper; use strict; require Exporter; use vars qw(@ISA @EXPORT $VERSION); @ISA = qw(Exporter); @EXPORT = qw(flip_words flip_boundary); $VERSION = 1.0; my $Separatrix = ' '; # default to blank; must precede functions sub flip_boundary { my $prev_sep = $Separatrix; if (@_) { $Separatrix = $_[0] } return $prev_sep; } sub flip_words { my $line = $_[0]; my @words = split($Separatrix, $line); return join($Separatrix, reverse @words); } 1;
This module sets three package variables needed by the Exporter and also initializes a lexical variable at file level called
A scope's lexicals cannot be examined or tinkered with from outside that scope, which in this case is the entire file below their point of declaration. You cannot fully qualify lexicals or export them either; only globals can be exported. If someone outside the module needs to look at or change the file's lexicals, they must ask the module itself. That's where the
This module would work the same even if its Speaking of style, the case of identifiers used in the Flipper module was not random. Following the Perl style guide, identifiers in all capitals are reserved for those with special meaning to Perl itself. Functions and local variables are all lowercase. The module's persistent variables (either file lexicals or package globals) are capitalized. Identifiers with multiple words have each of these separated by an underscore to make it easier to read. Please don't use mixed capitals without underscores - you wouldn't like reading this book without spaces, either. See AlsoThe discussion on file-scoped lexicals in perlmod (1); the "Scoped Declarations" section in Chapter 2 of Programming Perl ; the section on "Programming with Style" in Chapter 8 of Programming Perl or perlstyle (1); Recipe 10.2 ; Recipe 10.3 |
|