Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

named arguments

by spurperl (Priest)
on Nov 21, 2004 at 06:43 UTC ( [id://409334]=perlmeditation: print w/replies, xml ) Need Help??

Dear monks,

Sometimes subroutines turn into large beasts, and there's not much one can do about it. Initialization constructors of complex classes for example. To make the class as configurable as possible, the constructor accepts many parameters. Tk's classes are a good example.

So, there comes a time in a life of a subroutine when I decide to make its arguments named - passing a hash of arg => value pairs into the function. This makes the arguments more manageable, allows to provide default values, etc.

Two questions I have for you:

  1. Where is the line, for you, between "need named arguments" and "don't need named arguments" ? 2 args ? 4 ? 27 ?
  2. What is your favorite way of doing it ? I like to name arguments in Tk's style (-arg) - because I find CAPPED_NAMES bulky, and non_capped_names can clash with symbols. I also use the ending @_ trick to provide default values inside the sub.

Replies are listed 'Best First'.
Re: named arguments
by dws (Chancellor) on Nov 21, 2004 at 07:51 UTC

    1. Where is the line, for you, between "need named arguments" and "don't need named arguments" ? 2 args ? 4 ? 27 ?

    For me it's less a matter of number than it is about how the arguments will be used. If they'll be used to add to or override someone else's values, then named args are the way to go. This lets me write, for one contrived example,

    sub foo { my ($self, %args) = @_; $self->bar( answer => 42, %args, );
    This lets foo have a dialog with bar that involves some overridable default behavior. A more common form of this is default constructor state.
    sub new { my ($class, %args) = @_; return bless { loglevel => 0, die_randomly => 0, %args, }, $class; }
    Here, the constructor provides default state that clients can override. Easy to do with named arguments; difficult to impossible with positional args.

Re: named arguments
by Zaxo (Archbishop) on Nov 21, 2004 at 06:51 UTC

    Two, maybe. The class name and one argument, unless all arguments fit into an array.

    That aside, I only use named arguments like you describe for classes based on a hashref. That way I can say,

    sub new { my $class = shift; bless {@_}, $class; }
    or whatever elaboration of that is needed.

    After Compline,
    Zaxo

Re: named arguments
by FoxtrotUniform (Prior) on Nov 21, 2004 at 08:26 UTC

    If you have more arguments than will usually fit on one (72-column, say) line, or if you expect that a function's arglist will change quite a bit over time, then named params are the way to go. Mostly, I try to avoid long arglists (I don't really use Perl's OO system, although one might say that I tend to write object-oriented code); anything that's hard to work with (like a long arglist) is a red flag for me, and I try to break it up into easy to work with pieces.

    --
    Yours in pedantry,
    F o x t r o t U n i f o r m

    "Anything you put in comments is not tested and easily goes out of date." -- tye

Re: named arguments
by etcshadow (Priest) on Nov 21, 2004 at 17:20 UTC
    I've actually adopted the reverse. It's not a question of when to use named arguments, it's a matter of when not to. That is: assume that all subs take named arguments, and you really have to convince me if a particular subroutine should have positional arguments.

    When you're managing a very large project that is constantly growing and changing, it's frankly the only way. Where I work we've actually got a whole slew of code conventions that center around making code future-change friendly, and this is the center-piece of them. Among the others are: giving all key-value pairs their own line, giving all array values their own line, and always putting (unnecessary) trailing commas on list and hash declarations. The point being: diffs and merges only affect the lines that actually changed semantically, and highlite what the actual change is.

    ------------ :Wq Not an editor command: Wq
      It's not a question of when to use named arguments, it's a matter of when not to.
      ++ on the coding conventions. I have come to the same conclusion. It doesn't take many compile errors to get into the habit of including the trailing comma. :-) Getting highly relevant & informative diffs is a nice gift too.
Re: named arguments
by Limbic~Region (Chancellor) on Nov 21, 2004 at 14:43 UTC
    spurperl,
    I used named arguments for Tie::Hash::Sorted for a very specific reason. Being optional, there is no way to indicate that you have the middle argument unless they are named. Starting out with only two options, I likely could have handled this by examining the arguments and reordering them as necessary, but I wanted to be able to account for future changes without breaking backwards compatability.

    Cheers - L~R

Re: named arguments
by rrwo (Friar) on Nov 21, 2004 at 20:47 UTC
    1. Where is the line, for you, between "need named arguments" and "don't need named arguments" ?

    Well, for one thing I like to keep the calling convention for all methods or subroutines in a module consistent.

    Sometimes it makes sense to follow the calling styles of similar modules, especially if the module is designed as an alternative.

    That said, I prefer using named arguments but sometimes use both, if there's a small number of arguments but many optional "options" to pass to a routine:

    $obj->method( $first, $last, \%options );
    2. What is your favorite way of doing it ? I like to name arguments in Tk's style (-arg) - because I find CAPPED_NAMES bulky, and non_capped_names can clash with symbols. I also use the ending @_ trick to provide default values inside the sub.

    I really dislike the Tk calling style with the beginning hyphen. CAPPED_NAMES are irritating, and I prefer to use them for constants and names of constant hash keys in objects. I don't find there to be a problem with non_capped_names clashing with symbols: if there's a clash, consider using different names.

Re: named arguments
by itub (Priest) on Nov 21, 2004 at 16:49 UTC
    Regarding the style, what's wrong with just using plain lowercase words? I personally don't like the Tk style; I just do my_sub(name => 'bob', color => 'blue', flavor => 'cherry'). Can the names clash with symbols if you use the double arrow operator? I haven't had any problems; the double arrow stringifies the word on its left.
      I designed the named parameters to start with a '-' in our current project---biggest mistake I could make.

      sub foo { my ($self, $params) = __params({ -a => '...', }, \@_); ... if ($params->{a}) {
      You see the mistake above? Happend all the time, until I was forced to add this to __params():

      foreach my $key (keys %$result) { my $tkey = $key; $tkey =~ s/^-//; $result->{$tkey} = $result->{$key}; } return $result; }

      Search, Ask, Know
Re: named arguments
by nothingmuch (Priest) on Nov 24, 2004 at 07:01 UTC
    Everyone provided good reasons for and against named arguments.

    As for the how, I feel one thing is still missing: Params::Validate. This module has a nice way of defining very accurately what you need to get, and a little function that you simply feed your arguments to, and get back a proper data structure from.

    It handles errors and all that.

    When I work, given time, I use Params::Validate on classes that are subclassed heavily, or used by other people. I don't bother with it in the more "internal" classes while i'm working due to lack of time.

    As the the actual style, I use non_capped_names because they're easiest to type. I've never had clashes with symbols, but for clarity I avoid reserved words (not that I haven't used any).

    Ciao!

    -nuffin
    zz zZ Z Z #!perl

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://409334]
Approved by ysth
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (3)
As of 2024-04-19 22:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found