vek has asked for the wisdom of the Perl Monks concerning the following question:
Esteemed monks, I seek your wisdom.
If you have a lot of arguments that you need to pass to a subroutine, is it preferrable to pass & access them individually:
do_stuff($foo, $bar, $foo_too, $bar_too, $foo_who_poo);
sub do_stuff {
my ($foo, $bar, $foo_too, $bar_too, $foo_who_poo) = @_;
}
Or pass & access by named parameter:
do_stuff(one=>$foo, two=>$bar, three=>$foo_too, four=>$foo_who_poo);
sub do_stuff {
my %args = @_;
}
Or is it purely personal preference?
I'm starting to get some 'feature creep' in my code and keep adding subroutine arguments as the specifications change. I'm thinking at the very least if I pass by named parameter I'll have some 'self-documenting' code.
What do you do?
Re: Accessing Subroutine Arguments
by Chmrr (Vicar) on Apr 04, 2002 at 00:07 UTC
|
Since this is the realm of coding style, it's almost certainly all personal preference. ;>
I know that I tend to prefer using a hash once I get above three or four parameters. Some of the reasons that I can think of why I tend to do so:
*shrug* All of the above are just personal preferences, yes. Do what seems to work best for you.
perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'
| [reply] [Watch: Dir/Any] [d/l] [select] |
(Ovid) Re: Accessing Subroutine Arguments
by Ovid (Cardinal) on Apr 04, 2002 at 00:32 UTC
|
The fewer parameters that you pass to a subroutine, the easier it tends to be to maintain (assuming that everything is nicely encapsulated and you're not using globals or something like that). This is because the logic of dealing with one variable is typically going to be simpler than the logic of dealing with multiple variables. However, if I must pass numerous parameters, I like to set a threshhold of say, 4 parameters, and switch to a named argument style.
Consider the following, which is easy to happen when reusing a lot of code:
some_func( $foo, $bar, $baz, $qux );
# in another program
some_func( $w, $x, $y, $z );
# yet another program
some_func( $amount, $rate, $limit, $exception );
With this, not only are you forced to pass multiple parameters (even if they are undef), but you have to remember the order of the parameters. This can be awkward. Hmm... do I have the third and fourth parameters reversed, or not? However, what if $limit is optional, and I can't remember the order of $rate and $exception? With named parameters, this is a moot point:
some_func(
exception => $exception,
amount => $amount,
rate => $rate
);
Cheers,
Ovid
Join the Perlmonks Setiathome Group or just click on the the link and check out our stats. | [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Accessing Subroutine Arguments
by Bobcat (Scribe) on Apr 04, 2002 at 02:10 UTC
|
I actually prefer to use the "named parameter" method. Not only does it lead to more readable code, but you can do neat things with defaults this way.
use strict;
use Data::Dumper;
sub foo {
my %opt = ( text => 'Default Text'
, style => 'Default Style'
, bar => 'belch'
);
%opt = ( %opt, @_ );
print Dumper \%opt;
}
foo(); # Options stay as specified above.
foo( bar => 'yuk' ); # $opt{text} and $opt{style} stay the same,
# $opt{bar} becomes 'yuk' instead of 'belch'.
I find this really handy for functions that can have a lot of obscure parameters that you only want to change once in a blue moon.
| [reply] [Watch: Dir/Any] [d/l] |
Re: Accessing Subroutine Arguments
by perrin (Chancellor) on Apr 04, 2002 at 00:30 UTC
|
At eToys we made named parameters part of our coding conventions. It really helped, and I would recommend it as a good way to help keep stupid bugs out of your code. | [reply] [Watch: Dir/Any] |
|
Just wondering, do you use named params when a sub takes, say, only two params?
| [reply] [Watch: Dir/Any] |
|
If a sub takes only two params, and is not part of the public interface, it's a judgement call based on the likelihood of that sub growing in the future. If it's part of the public interface, I would used named params even if there was only a single one. It's insurance against changing a bunch of other classes later on.
| [reply] [Watch: Dir/Any] |
Re: Accessing Subroutine Arguments
by lshatzer (Friar) on Apr 04, 2002 at 00:56 UTC
|
In my progress as a perl programmer, I started out with your first method, passing in a list of variables, and then grabbing them in that order in the subroutine.
As it got more advanced, I started using the second, (usually with a hash reference or something similar like you posted).
Then in some cases, where I keep passing the same value, since it does not change much, I found creating an object, blessing it, and making methods to do the work was a little easier to do.
| [reply] [Watch: Dir/Any] |
Re: Accessing Subroutine Arguments
by rjray (Chaplain) on Apr 04, 2002 at 00:38 UTC
|
As the previous respondent pointed out, this is more in the area of personal style preference, but I also agree with him that the nature of the situation you describe lends itself to the hash-table/named-args approach.
When I write subroutines, I give some time to consider (a) the scope of the routine itself (not in the lexical sense, but in the sense of, "How big and significant is this likely to become?"), and (b) easy will it be to document clearly for the sake of other users? For that matter, the "other users" question can often be a deciding point-- one utility-script I package with RPC::XML uses long lists of parameters between routines, but no one else is going to use that routine independantly, it will only ever be part of the utility script (which harkens back to the "scope of use" question).
I realize this is no more a definative answer than the previous post was, because this is not an absolute cut-and-dried situation. However, just for arguments' sake, I'll say that in my opinion you should go with the hash-table approach for the situation you specifically describe.
--rjray
| [reply] [Watch: Dir/Any] |
Re: Accessing Subroutine Arguments
by Juerd (Abbot) on Apr 04, 2002 at 07:14 UTC
|
Or is it purely personal preference?
It is. I start using named arguments when a sub has more than two.
If does require that your sub names are logical, though.
readfile('foo.txt');
is already self-documenting, while
readfile( file => 'foo.txt' );
is redundant.
U28geW91IGNhbiBhbGwgcm90MTMgY
W5kIHBhY2soKS4gQnV0IGRvIHlvdS
ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
geW91IHNlZSBpdD8gIC0tIEp1ZXJk
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Accessing Subroutine Arguments
by trs80 (Priest) on Apr 04, 2002 at 14:20 UTC
|
For me passing a hash(ref) makes my life easier, especially in the earlier stages of development when I don't even know for sure what options may need to be available to a method/sub or in the (un)likely event that the requirements should change you have more flexibiltiy.
| [reply] [Watch: Dir/Any] |
|
|