Typeglobs#
A typeglob is a single name that holds every variable type with that name in a package — the scalar $foo, the array @foo, the hash %foo, the sub &foo, the filehandle foo, and the format foo all share one symbol-table entry, and *foo is the way to talk about that entry as a value. The sigil is *, deliberately chosen because the asterisk reads as “all”.
*foo # the typeglob — all of $foo, @foo, %foo, &foo, etc.
*foo{SCALAR} # ref to $foo
*foo{ARRAY} # ref to @foo
*foo{HASH} # ref to %foo
*foo{CODE} # ref to &foo
*foo{IO} # the filehandle, if foo is one
*foo{NAME} # the name "foo" — a string
*foo{PACKAGE} # the package name — a string
In modern Perl, typeglobs come up rarely. References cover most of what they used to be needed for. The remaining legitimate uses are package aliasing, filehandle creation in older idioms, and a few introspection hooks.
What a typeglob does#
The single most useful sentence about typeglobs:
Assigning to a typeglob makes one name mean another name.
*foo = *bar; # $foo, @foo, %foo, &foo, FH foo all alias $bar, @bar, %bar, &bar, FH bar
After that assignment, modifying $foo modifies $bar, calling foo() calls bar(), and so on for every type. The two names are now genuinely the same storage — not a copy.
Assigning a reference to a typeglob aliases only that one type:
our @items;
*shortcut = \@items; # only @shortcut aliases @items; $shortcut and %shortcut unchanged
This is how the Exporter module installs imported subs into the caller’s package: *caller_package::name = \&exporter_package::name. Each imported function gets one slot of one glob assigned, so the rest of the destination package’s variables under that name are untouched.
*name = \&sub — the standard import idiom#
package My::Util;
sub greet { "Hello, $_[0]!" }
package main;
*greet = \&My::Util::greet; # import greet into main::
print greet("world"); # "Hello, world!"
This is the mechanism that use invokes via Exporter::import — the importing package gets a glob assignment for each requested name. Exporter does it; you can do it by hand for cases Exporter doesn’t fit.
Local glob aliases#
local *name = \$thing is a temporary alias that auto-restores when the enclosing scope exits:
our $config = "default";
sub run_with_config {
my ($alt_config, $code) = @_;
local *config = \$alt_config; # only inside this sub
$code->(); # any read of $config reads $alt_config
}
run_with_config("test", sub {
print "config is $config\n"; # "config is test"
});
print "config is $config\n"; # "config is default" — restored
This is a heavyweight mechanism that has largely been replaced by plain local $config = $alt_config; for scalars and explicit parameter-passing for everything else. The case where it still matters is when you need to alias a filehandle across the call of arbitrary user code (see below).
Filehandle typeglobs#
Before Perl 5.6’s “open my $fh” idiom, filehandles had to be named by package globals or passed as typeglobs:
# Old style — bareword filehandle in a glob slot
open FH, '<', $path or die $!;
while (<FH>) { ... }
close FH;
# Pass to a sub:
sub print_to { my $fh = shift; print $fh "stuff\n" }
print_to(\*FH); # ref-to-glob
# Modern style:
open my $fh, '<', $path or die $!;
while (<$fh>) { ... }
close $fh;
print_to($fh); # plain scalar ref to IO
The modern style is preferred everywhere new code is written. The typeglob-filehandle form survives in three places:
The standard handles —
STDIN,STDOUT,STDERRare bareword filehandles backed by the typeglobs*STDIN,*STDOUT,*STDERR. You see these in error messages and reset code:print STDERR "error\n"; *STDOUT = *STDERR; # redirect all STDOUT to STDERR for the rest of the program
Returning newly-created filehandles — before lexical filehandles, the way to return a fresh handle from a sub was to
local *FHand return*FH:sub new_handle { my $path = shift; local *FH; open FH, $path or return; return *FH; # the glob outlives the local because it was returned }
Modern equivalent:
sub new_handle { my $path = shift; open my $fh, $path or return; return $fh; }
Selecting a different default output handle —
selectreturns and accepts a filehandle, in glob-or-string form:my $old = select(STDERR); # subsequent print without explicit fh writes to STDERR print "errors-only output\n"; select($old); # restore
*foo{THING} — the slot accessors#
*foo{THING} returns a reference to one slot of the glob, or undef if that slot is empty:
*foo{SCALAR} # \$foo if $foo has been touched
*foo{ARRAY} # \@foo if @foo has been touched
*foo{HASH} # \%foo if %foo has been touched
*foo{CODE} # \&foo if &foo defined
*foo{IO} # the IO handle, or undef
The *foo{IO} form is the one place you regularly see THING syntax in modern code. It’s how you ask “is this scalar holding a filehandle”:
sub is_handle {
my $thing = shift;
return defined ref($thing) && (
ref($thing) eq 'GLOB'
|| (ref(\$thing) eq 'GLOB' && defined *$thing{IO})
);
}
The standard introspection helper that wraps this is Scalar::Util::openhandle.
*foo{SCALAR} has a quirk: it always returns something — the package’s $foo slot is created on demand. The other accessors return undef when the slot is empty.
What replaces typeglobs#
For the patterns where typeglobs used to be the only answer, the modern alternatives are:
Old typeglob pattern | Modern replacement |
|---|---|
Pass a filehandle to a sub | Lexical FH: |
Return a filehandle from a sub | Lexical FH: |
Alias |
|
Pass an array by reference |
|
Install an imported sub |
|
Localised global alias |
|
The *here = \@there package-aliasing pattern is the one that typeglobs still own outright — there’s no “alias one package variable to another” mechanism that doesn’t go through a glob. Inside Exporter-using modules that mostly happens automatically.
See also#
References — the modern alternative to globs for most “indirect access” patterns.
Scalars — the dynamic-typing story. Globs are a separate type:
ref \*FHreturns'GLOB'.local— the safe way to install a temporary glob alias.select— the selected-output-handle function that takes glob or string handle names.Scalar::Util—openhandle,reftype,blessedfor runtime introspection.Symbol— generate fresh anonymous globs and qualify package names. (No local reference page yet.)