Those with encyclopedic knowledge of the perl6-language list will recall my
impassioned, but ultimately futile plea for required named parameters--that
is, required arguments to a function that must be supplied as "pairs" rather
than positionally.

Here's a post from the middle of that old thread:

http://www.nntp.perl.org/group/perl.perl6.language/14689

Okay, so no one seemed to buy my argument the last time around, but now I'm
reading A12 and I see things like this:

http://www.perl.com/pub/a/2004/04/16/a12.html?page=7#the_default_constructor

> The arguments for the default constructor are always named arguments, hence
> the *%_ declaration to collect all those pairs and pass them on to bless.

http://www.perl.com/pub/a/2004/04/16/a12.html?page=9#multi_submethod_build

> It is not likely that Perl 6.0.0 will support multiple dispatch on named
> arguments, but only on positional arguments. Since all the extra arguments to
> a BUILD routine come in as named arguments, you probably can't usefully multi
> a BUILD (yet).

These passages may not seem directly relevant to my earlier argument, but I
think they do add something to the topic.

The first one confuses me a bit.  The default constructor has a *%_
signature, which means it slurps up all the named parameters.  It's obvious
that the default constructor is only interested in named params, but the
signature doesn't really enforce this, AFAICT.  If I call a default
constructor like this:

    $dog = Dog.new(name => 'Fido', age => 7, 2, 'Brown', Collar.new());

then Perl 6 won't say boo at either compile time or runtime.  Or maybe I'm
wrong, but either way this isn't really an argument for required named
params since there are no required args to the default constructor anyway.
But I'm getting there (I hope), so bear with me :)

I'm not sure what the above would do, assuming the default new() doesn't
have a [EMAIL PROTECTED] term waiting at end of its signature to slurp up the args 7,
'Brown', and Collar.new().  Would those args just be ignored?  And what if
it was called like this?

    $dog = Dog.new(2, name => 'Fido', age => 7, 'Brown', Collar.new());

Is that a compile-time or runtime error?  Hm.  Anyway, let's move on.

Let's supposed that I don't like the default constructor and want to replace
it with one of my own.  I decode that an object of my Dog class cannot be
instantiated without a name, age, and id.  But being a good Perl 6 citizen,
I document the usage of my constructor like this:

    $dog = Dog.new(name => 'Fido', age => 7, id => 2);

After all, according to A12, "arguments for the default constructor are
always named arguments", so I'm trying to follow suit.  I don't want my
customized constructor to be needlessly different than the default
constructor.  Unfortunately, the signature for my constructor has to be:

    method new($name, $age, $id, *%rest) { ... }

which means that, regardless of how I document the API, someone can do this:

    $dog = Dog.new('Fido', 2, 7);

and there's nothing I can do to stop them.

...so, did you catch the fact that the second example is a two year-old dog
instead of a seven year-old dog?  Maybe, maybe not, which is part of why I,
as the API designer, decided that those params should named.

Even more importantly, I decided to use named params because there's no
"natural" or implied order for the name, age, and id attributes.  It's
completely arbitrary.

Okay, so it's arbitrary.  Then why can't I just maintain that arbitrary
order forever and ever?  In fact, if I do nothing, it will be maintained.
So what's the problem?

Yes, the answer is that "it's the principle."  Name, age, and id are
required, but there is no implied order.  I want them to be named params.  I
am the API designer.  I think it will reduce errors and make code that uses
my Dog object easier to read and maintain.

It's not as if I'm forbidding Dog users from using the indirect object
syntax or something like that.  My demands are modest, useful,  and
certainly no more onerous or "B&D"-esque than choosing method names or
deciding which arguments are required or any of the other things that an API
designer does. 

Obviously the Perl 6 Language Design Illuminati have at least a few thoughts
in a similar direction.  "The arguments for the default constructor are
always named arguments" because constructors often initialize lots of
attributes, and those attributes rarely have a natural or implied order.
Constructors just plain look and work better with named params.  (The only
possible exception is a special-case for a single argument.)

But, ha ha, that's too bad if you also decide that some of the constructor
params are required!  Even if nothing has changed about the lack of a
natural or implied order of the arguments, you, as the API designer, are
forced to both *choose* and *maintain forever* an arbitrary order for your
params!

I think this is a bad thing.

This may seem like it has turned into just a repeat of the Synopsis 6
discussion, but I wanted to point out that A12 has several examples of
situations where named params are the best, most natural fit.  I don't think
any of those situations are intrinsically limited to also being concerned
only with optional params.

I know we are running out of special characters, but I really, really think
that required named parameters are a natural fit for many common APIs.  A12
has reinforced that belief.  Save me, Dami-Wan Wallnobi, you're my only
hope...

-John



Reply via email to