More complex usage of references

References to Subroutines

In the same way you reference individual items such as arrays and scalar variables, you can also point to subroutines.

To construct such a reference, you use the following type of statement:

$pointer_to_sub = sub { ... declaration of sub ... } ;

Notice the use of the semicolon at the end of the sub declaration. To call a subroutine by reference, you must use the following type of reference:

&$pointer_to_sub( parameters );

This is pretty logical: you are de-referencing the $pointer_to_sub and using it with the ampersand (&) as a pointer to a function.

The code within a sub is simply a declaration created through a previous statement. The code within the sub is not executed immediately, however. It is compiled and set for each use. That means that you can store procedures like regular variables, make them elements of array or hash, etc.

The Anonymous Hash Composer

You can create a reference to an anonymous hash by using braces:

 

$hashref = {
    'Adam'  => 'Eve',
    'Clyde' => 'Bonnie',
};

 

The values above are literal strings; variables and expressions would work as well. Also, for the values (but not the keys) of the hash, you can freely mix anonymous hash and array composers to produce as complicated a structure as you want.

These braces work like this only where the Perl parser is expecting a term in an expression, and should not be confused with the braces that are functioning as operators when used to subscript a hash (though there is an obvious mnemonic association with hashes). Braces inside a quoted string do not result in the interpolation of a reference to an anonymous hash. Rather, such braces become literal elements in the string. (However, the same caveat about interpolating expressions applies to braces as it does to brackets.)

Since braces are also used for several other things including BLOCKs, you may occasionally have to disambiguate braces at the beginning of a statement by putting a + or a return in front so that Perl realizes the opening brace isn't starting a BLOCK. For example, if you wanted a function to make a new hash and return a reference to it, you have these options:

 

sub hashem {        { @_ } }   # silently WRONG
sub hashem {       +{ @_ } }   # ok
sub hashem { return { @_ } }   # ok

 

The Anonymous Subroutine Composer

You can create a reference to an anonymous subroutine by using sub without a subroutine name:

$coderef = sub { print "Boink!\n" };

 

Note the presence of the semicolon, which is required here to terminate the expression. (It wouldn't be required after the declaration of a named subroutine.) A nameless sub {} is not so much a declaration as it is an operator - like do {} or eval {} - except that the code inside isn't executed immediately. Instead, it just generates a reference to the code and returns that. However, no matter how many times you execute the line shown above, $coderef will still refer to the same anonymous subroutine.[4]

[4] But see later about closures. Even though there's only one anonymous subroutine, there may be several copies of the lexical variables in use by the subroutine, depending on when the subroutine reference was generated.

Object Constructors

Subroutines can also return references. That may sound trite, but sometimes you are supposed to use a subroutine to create a reference rather than creating the reference yourself. In particular, special subroutines called constructors return references to objects. An object is simply a special kind of thingy that happens to know which class it's associated with. Constructors know how to create that association. They do so by taking an ordinary thingy and turning it into an object (which remains a thingy even while it's also being an object). The operator that a constructor uses to do this is called bless, so we can speak of an object as a blessed thingy. Constructors are customarily named new(), but don't have to be. They're usually called in one of two ways:

$objref = new Doggie Tail => 'short', Ears => 'long';
   # same as
$objref = Doggie->new(Tail => 'short', Ears => 'long');

 

See Chapter 5, Packages, Modules, and Object Classes, for a discussion of Perl objects.