in reply to How should named paramater keys be named?

Why is a hyphen often used as the first character in named parameters?

Historically, because it allowed getopts to be used to parse/validate sub args?

And do the 'good reasons' (if any exist) outweigh the inconvenience of defeating part of the usefulness of the fat comma operator?

No. (Because there are no good reasons.)

Additionally, the justifictions for named parameters are overstated.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re^2: How should named paramater keys be named?
by DeadPoet (Scribe) on Jul 02, 2011 at 01:32 UTC

    Just my 2 cents on the matter.

    First, I love named parameters, but use both styles -- named and unnamed. It all just boils down to the level of confidence that you have in the values, and respective ordering, that have been passed. If it is an internal function, method, subroutine, whatever that you are certain of the parameters, then named parameters are not really needed. However, if it is an interface exposed to the public where you are not certain of the ordering, then named parameters may be in order.

    Next, there is no substitute for checking what is passed. Unexpected, or bad, programmatic behaviour happens when parameters and return codes are not checked. Never assume the sky is always blue.

    Finally, BrowserUk is correct in saying that all the bits add up. One needs to take in to context what is being done and who is doing it. Memory footprint, CPU usage, and overall responsiveness of an application is just as important as what the application accomplishes. Too often one comes across a "Swiss army knife" application that does everything but does nothing well because of its' design. Personally I would rather have an application that does one thing really well than an application that tries to do many things and is hard to maintain.

    Like I said, just my two cents.

    --Poet

      However, if it is an interface exposed to the public where you are not certain of the ordering, then named parameters may be in order.

      You really think that remembering the ordering of parameters is harder than remembering the names, spelling, casing, presence or absence of leading hyphens etc?

      Do you you use (or just know of) a non-constructor api that you feel really benefits from the use of named parameters?


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        The LWP::UserAgent/WWW::Mechanize API (and especially the WWW::Mechanize::Firefox API) has lots (and lots) of optional parameters, which are mostly filled in as defaults from the object when left out or left alone. The first such example in WWW::Mechanize::Firefox is

        $mech->progress_listener( $source, %callbacks )

        ... where you specify the callbacks by name instead of by position, as usually, you want only to set one or two callbacks.

        The same counts for the ->get() method:

        $mech->get( $url, %options )

        Here, the options can specify a target filename where to store the response, whether to bypass the cache etc.. All of these parameters are fairly orthogonal and it wouldn't make much sense to have them positional in my opinion.

        Two APIs that constantly trip me up is the DateTime API and the Imager::Color API. The DateTime API wants me to always specify named parameters when I'm calling any function even though the method only allows one parameter and makes sense for only one parameter. The Imager::Color API raises no warning for:

        my $blue = Imager::Color->new( 0, 0, 255 );

        ... but creates no sensible object either. It wants

        my $blue = Imager::Color->new( r => 255, g => 0, b => 0 );

        Once again it depends on the complexity of the parameters that are being supplied. One, two, three parameters exposed to the public maybe not an issue, and agreeably named parameters probably not needed.

        However, if the interface in to the whatever you are calling requires a more complicated set up, then I would say that named parameters are in order. Now with that said, when using named parameters they better be consistent throughout the entire program. Moreover, I would go so far as to say they should also be lower case and clearly documented. Personally I see named parameters having value, but the value is only obtained where exposed to the public. Code that is on the back end that users cannot call directly why would they be needed--you already have established programmatic control over the parameters.

        Yes, I use named parameters outside of a constructor -- my previous restrictions still apply ( internal NO, user called YES ). An example would be when I want to enable a local debug. Keep in mind that the routine already has other values being passed.

        sub foo { my $o = { q{debug} => 0, ## debug 0|1. q{db} => SQL_DB, ## sql db. q{host} => SQL_SERVER, ## sql server. q{port} => SQL_PORT, ## sql server port. q{user} => SQL_USER, ## sql user. q{pass} => SQL_PASS, ## sql user pass. @_ }; ## do your safety checks... my $dsn = q{DBI:mysql:database=} . $o->{'db'} . q{;host=} . $o->{'host'} . q{;port=} . $o->{'port'}; my $objSQL = eval { DBI->connect( $dsn, $o->{'user'}, $o->{'pass'}, { 'PrintError' => 0, 'RaiseError' => 0 } ); }; if ( ( $@ ) || ( ! defined $objSQL ) ) { ## maybe we only want to show the error if in debug?? print STDERR $DBI::errstr if ( $o->{'debug'} ); return undef; } DBI->install_driver( q{mysql} ); return $objSQL; }

        Now, I did not run check the code above, and it is ONLY an example of what can be done. Also, I do not expect everyone to agree with the code. So, not only does this allow a user to call the function, method, subroutine, etc... but it provides simple named parameters by which it can be called. More importantly, it allows the end user to call it without having to care about the order and if the parameter is not specified then it is defaulted. I understand that one cannot always default to a meaningful value, but this is just an example. As far as my style goes, I do not like the leading hyphen, nor do I like the mixed case, such as the DBI Connect implements. But that is just my style. Honestly, I prefer the shorter single case format.

        Finally, named parameters have their place and can provide value. The trick is to balance how and when they are used. Is there a cost? Yes. Can they provide a more robust public interface? Yes. Can they be overused? You better believe it.