Item 24: Avoid using @_ directlyunless you have to.Unlike many programming languages, Perl has no built-in support for named or "formal" parameters. The arguments to a subroutine are always passed in via the argument list variable @_ . It is up to the author of the subroutine to give the arguments names and check them for consistency. In general, you should always start off a subroutine by copying its arguments and giving them names . The preferred method is to use my : This subroutine will remove digits from a string.
The idiomatic way to read arguments passed to a subroutine is to use shift to get them one at a time or a list assignment to read them all: This subroutine counts different types of chars in a string. Usage: char_count $str, $chars1, $chars2, ...
Another reason to copy and name subroutine arguments is that the elements of @_ are actually aliases for the values that were passed in. Modifying an element of @_ modifies the corresponding subroutine argumenta sort of " call by reference" semantics. Subroutines can modify their arguments, but attempts to do so can fail if the arguments are read-only:
If we try to call this subroutine as txt_file_size "test" , it fails with an error message as it tries to modify the read-only value "test" . Also, if we call it with a modifiable argument, say txt_file_size $myfile , it may append '.txt' to the argument, which is likely not what we want. But sometimes this aliasing "feature" turns out to be genuinely useful. For example: This subroutine will normalize some values "in place."
If you are trying to optimize for speed, it may be faster for you to use @_ without copying it, because copying values takes a significant amount of time. If you do so, remember that array subscripting tends to be slow, so try to use constructs like foreach , grep , and map that allow you to iterate over an array without having to subscript its elements repeatedly. The best approach, of course, would be to write two or more different versions and Benchmark them (see Item 37). Even though subroutine arguments are passed as aliases, any array arguments is flattened into a list. You can modify the elements of an array argument, but not the array itself: Throw out the "bad" elementNOT!
When we run this program, we get: % tryme in no_bad: ok better fine great good after no_bad: ok better fine great bad good Finally, on a slightly different topic, subroutines that are called with no arguments usually have an empty @_ of their own. However, if a subroutine is called with an ampersand and no parentheses, it inherits the current @_ :
|