Hack #75. Find All Symbols in a Package

Explore symbol tables without soft references.

One of the earliest temptations for novice programmers is to use the contents of one variable as part of the name of another variable. After making one too many costly mistakes or showing such code to a more experienced programmer, novices start to use the strict pragma to warn them about dubious constructs.

However, several advanced features of Perl, such as the implementation of the Exporter module, are only possible by reading from and writing to the symbol table at run time. Normally strict forbids this—but it's possible to access global symbols at run time with strict enabled.

This is an easy way to find out if a symbol—such as a scalar, array, hash, subroutine, or filehandle—exists.

The Hack

Suppose you want to check whether a specific type of variable is present in a given namespace. You need to know the name of the package, the name of the variable, and the type of the variable.

Defining the following subroutine in the UNIVERSAL package makes the class method contains_symbol available to any package:[4]

my %types = ( '$' => 'SCALAR', '@' => 'ARRAY', '%' => 'HASH', '*' => 'IO', '&' => 'CODE', ); sub UNIVERSAL::contains_symbol { my ($namespace, $symbol) = @_; my @keys = split( /::/, $namespace ); my $type = $types{ substr( $symbol, 0, 1, '' ) } || 'SCALAR'; my $table = \\%main::; for my $key (@keys) { $key .= '::'; return 0 unless exists $table->{$key}; $table = $table->{$key}; } return ...

Get Perl Hacks now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.