Front page | perl.perl5.porters |
Postings from October 2022
Re: Named argument syntax (was Re: PSC #049 2022-01-07)
Thread Previous
|
Thread Next
From:
Dave Mitchell
Date:
October 12, 2022 09:53
Subject:
Re: Named argument syntax (was Re: PSC #049 2022-01-07)
Message ID:
Y0aOdyT54vo97b8z@iabyn.com
On Sat, Oct 08, 2022 at 03:23:45PM +0200, Ovid wrote:
[stuff]
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
:@foo
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);
foo(@a,1);
If anyone is assuming/proposing anything different, they'll need to speak
up.
As regards using ':$a' at the call site as shorthand for ('a', $a),
I had a more general proposal: for a scalar variable,
=$foo
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
separators.
--
Justice is when you get what you deserve.
Law is when you get what you pay for.
Thread Previous
|
Thread Next