develooper Front page | perl.perl5.porters | Postings from October 2022

Re: Named argument syntax (was Re: PSC #049 2022-01-07)

Thread Previous | Thread Next
Dave Mitchell
October 12, 2022 09:53
Re: Named argument syntax (was Re: PSC #049 2022-01-07)
Message ID:
On Sat, Oct 08, 2022 at 03:23:45PM +0200, Ovid wrote:

Responding to several points.

1) Ordering: \:@foo versus :\@foo

I can't fully remember my reasoning, but elsewhere in the proposal I
suggested the following full ordering for parameter syntax, taking into
account all proposed features:

    ?                 Optional start of query parameter
    ?                 Optional start of boolean query parameter (??$x)
    Int               Optional type
    '\' or '*'        Aliasing
    :                 Named parameter
    [$@%]foo          Sigil with optional parameter name
    !                 Optional "croak if undef"
    :foo(...)         Optional attribute(s)
    ?                 'default' default value (instead of default value below)
    = ....            Default value
    where/as/isa/is ... Constraint

I think the idea was that \ comes before the : because intuitively its an
operator that's applied after the binding. I.e. the pseudo expression


triggers a search of the argument list for a pair of scalars of the form
('foo', X), then the pseudo-operator '\' is "applied" to the expression
:@foo to dereference the value X and alias it to @foo.

Similarly, the idea is that the stuff associated with binding the name of
a parameter with an argument should be as close as possible to the name.

But I'm not 100% wedded to that ordering.

2) Shortening :\@foo to :@foo

In some ways I like this idea, but there are some consistency problems.

First, aliasing can be done on positional as well as named parameters; for
the former, you'd still need the '\':

    sub positional(\@x, \@y); {...}   positional ([..], [...]);

    sub named(:@x, :@y);      {...}   named      (x => [..], y => [...]);

Also there are two types of aliasing: '\' includes a deref of the passed
reference and consumes a single argument; '*' does a direct alias:

    # alias $first   to $_[0] (as was),
    # alias $rest[0] to $_[1], $rest[1] to $_[2] etc.

    sub foo (*$first, *@rest) {...}
    foo($x,$y,$z); # $z is aliased to $rest[1]

    # deref each arg then alias:

    sub foo (\$a, \@b, \%c) {...} foo(\$x,[...], {...});

So the rule becomes: '\' is omitted for named array and hash parameters,
but must be kept for named scalar parameters and for all types of
positional parameter; '*' must be kept for all types of named and
positional parameters.

It becomes a question of how common is the passing of named aggregate
references to allow a confusing inconsistency in the syntax?

3) calling conventions, e.g. foo('x' => $x, :$y, :$z)

First, a very important point is that I've always assumed that named
parameters in perl aren't special; the arguments to a function are always
a simple perl list, and named parameters just consume a pair of arguments
from that list, while interpreting the first argument as a string which
needs to be matched to a parameter name.

So for this function definition,

    sub foo(:$x, :$y, $:z) { ....}

all the following calls are equivalent, and do the same as
my ($x,$y,$z) = (1,2,3):

    foo(x => 1, y => 2, z => 3);

    foo(x => 1, z => 3, y => 2);

    @a = ('z', 3, 'y', 2, 'x);

If anyone is assuming/proposing anything different, they'll need to speak

As regards using ':$a' at the call site as shorthand for ('a', $a),
I had a more general proposal: for a scalar variable,


anywhere in perl code (apart from column 0 at the start of a line)
would be compile-time syntactic sugar for ('foo', $foo), which could be
used in a function call, or anywhere else where it make sense, e.g.

    my @point = (=$x, =$y, =$z);

is short for

    my @point = (x => $x, y => $y, z => $z);

I rejected using a colon for this feature (even though it would have
aesthetically pleasing mirroring with named parameter syntax), as it would
clash with the ?: ternary operator, and potentially with package name

Justice is when you get what you deserve.
Law is when you get what you pay for.

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About