| home / programming / perl / professional / chap7 / 3 |
[previous] |
|
Named ParametersUnlike other languages such as C or Java, Perl does not have any way to define formal parameter names for subroutines. The closest it gets is prototypes combined with retrieving parameters as lexical variables, as in:
However, we can implement named parameters using a hash. This provides an elegant way to pass in parameters without having to define them formally. The trick is to assign the @_ array to a hash variable. This converts the passed list into key-value pairs:
The disadvantage of this approach is that we have to name all the parameters that we pass. It is also slower, since hashes are inherently slower than arrays in use. The advantage is that we can add more parameters without forcing the caller to supply parameters that are not needed. Of course, it also falls upon us to actually check the arguments passed and complain if the caller sends us arguments that we do not use. We can call this subroutine using the => operator to make it clear that we are passing named parameters:
We can also write the subroutine so that it accepts both named parameters and a simple list. One common technique borrowed from UNIX command line switches is to prefix named arguments with a minus, to distinguish them from unnamed arguments. To determine how the subroutine has been called, we just check the first character of the first parameter to see if it is a minus:
In this version of the volume subroutine we handle both simple and named parameters. For named parameters we have also taken advantage of the fact that we know the names of the parameters to report a handy informative warning if any of them are undefined. Named parameters allow us to create a common set of parameters and then add or override parameters. This makes use of the fact that if we define a hash key twice, the second definition overrides the first:
Before leaving the subject of named parameters, it is worth briefly mentioning the Alias module, available from CPAN. Alias provides the subroutines alias and attr, which generates aliases from a list of key-value pairs. Both subroutines use typeglobs to do the job. The alias subroutine takes a list of key-value pairs as its argument, and is therefore suited to subroutines. The type of variable defined by the alias is determined by the type of value it is aliased to; a string creates a scalar, a list creates an array. Here is yet another volume subroutine that uses alias:
However, alias suffers from three serious deficiencies. The first is that it is not compatible with strict vars; if we want strict variables we will have to declare all the aliased variables with use vars or (preferably) our. Another is that alias creates global aliases that persist outside the subroutine, which is not conducive to good programming. The third is that if we only use the variable once we'll get a warning from Perl about it. The script above does not do that because of the last line. Comment out that line, and all three variables will generate used only once warnings. attr takes a reference to a hash and creates aliases based on the keys and values in it. attr $hashref is similar to alias %{$hashref}, but localizes the aliases that it creates. It is ideal to use with object methods for objects based around hashes since each object attribute becomes a variable (hence the name):
We can also define 'constants' with the const subroutine. This is actually just an alias for alias (it's even defined using alias inside the module, and must be imported explicitly:
Attempting to modify the value of a constant produces an error:
The Alias module also provides several customization features, mainly for the attr subroutine, which allows us to control what gets aliased and how. Refer to 'perldoc Alias' for a rundown and some more examples. |
| home / programming / perl / professional / chap7 / 3 |
[previous] |
Revised: March 22, 2001
Created: March 22, 2001