Although Perl provides no method of automatically naming parameters in the subroutine to which they are passed (in other words, no " formal parameters" [6] see Item 23), there are a variety of ways that you can call functions with an argument list that provides both names and values. All of these mechanisms require that the subroutine being called do some extra work while processing the argument list. In other words, this feature isn't built into Perl either. However, this is a blessing in disguise. Different implementations of named parameters are appropriate at different times. Perl makes it easy to write and use almost any implementation you want.
A simple approach to named parameters looks like this: Parse named parameters with a hash.
You would call it in this way: uses_named_params(bar => 'myval1', bletch => 'myval2'); That wasn't very many lines of code, was it? And they were all fairly simple. This is a natural application for hashes. You may want to allow people to call a subroutine with either " positional" parameters or named parameters. The simplest thing to do in this case is to prefix parameter names with a minus sign. Check the first argument to see if it begins with a minus. If it does, process the arguments as named parameters. Here's one straightforward approach:
You can call this subroutine with either named or positional parameters: uses_minus_params(-foo => 'myval1', -xtra =>'myval2'); uses_minus_params('myval1', 'myval2'); Note Stay away from single-character parameter names, for example, -e and -x . In addition to being overly terse, those are file test operators (see Item 56). If you use this method for processing named parameters, you refer to the arguments inside your subroutine by using a hash whose keys are prefixed with minus signs, for example, $param{-foo} , $param{-bar} . Using identifiers preceded by minus signs as arguments or keys may look a little funny to you at first ("Is that really Perl?"), but Perl actually treats barewords preceded by minus signs as though they were strings beginning with minus signs. This is generally convenient , but this approach does have a couple of drawbacks. First, if you want to use the positional argument style and need to pass a negative first argument, you have to supply it as a string with leading whitespace or do something else equally ungainly. Second, although an identifier with a leading minus sign gets a little special treatment from Perl, the identifier isn't always forcibly treated as a string, as it would be to the left of => or alone inside braces. [7] Thus, you may have to quote a parameter like -print , lest it turn into -1 (while also printing the value of $_ ).
There are plenty of applications where these issues don't present a problem, but there are some where where one or both do. In this case, you may want to resort to yet another technique, which is to pass named parameters in an anonymous hash:
The syntax for using named and positional parameters now looks like: uses_anon_hash_params( {foo => 3, test => 10} ); uses_anon_hash_params(-123, 345); Or even: uses_anon_hash_params {foo => 3, test => 10}; This is a pretty complicated piece of boilerplate to have at the beginning of a subroutine. If you have several subroutines that accept named parameters, you will probably want to create a subroutine that does most of the work. Here is a subroutine that implements the anonymous hash technique: Process parameters in an anonymous hash with a subroutine.
And here's how you might use it:
Each of the techniques illustrated here has its own advantages and drawbacks. Use the technique that best suits your application, or, if none is quite right, adapt one as necessary. |