Mailing List Archive

Named argument syntax (was Re: PSC #049 2022-01-07)
On 2022-01-19 4:41 a.m., Dave Mitchell wrote:
> 1) Another advantage of not populating @_ is that it removes a whole bunch
> of edge cases concerning what happens if @_ is modified during arg
> processing. In particular things become more complicated if we ever
> implement named args: this is where the caller does foo(y =>2, x =>1) to
> call sub foo(:$x, :$y) {} - here the processing of default args etc
> doesn't follow a simple L-R ordering and it's more likely that @_ could
> get modified mid-processing.

I know this isn't the main point of what you're saying, but I want to address
the matter of named arguments.

Your example code using "=>" may have just been representative and not literal.

But I want to argue that when/if Perl does add native support for named
parameters/arguments, which I hope it does, I feel that we must use a NEW syntax
to indicate it, and NOT use "=>".

While Perl devs are used to "=>" to indicate fake named parameters/arguments,
the fact remains that this is really just a "fat comma" and a lot of code is
going to break if Perl starts saying that the syntax now maps to named parameters.

I propose following an example which is very common in other languages and data
formats, and is also better Huffman coded, which is to use the colon ":" to
indicate named parameters or arguments.

This shouldn't conflict with any other use of the colon that I'm aware of.

So these two things should continue to have the same meaning, and map to 2
positional parameters:

foo('x', 'y')
foo(x => 'y')

... and this would continue to map to a single positional parameter which is a
hashref:

foo({x => 'y'})

Whereas this would map to a named parameter:

foo(x: 'y')

-- Darren Duncan
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
On Sat, Jan 22, 2022 at 12:39 AM Darren Duncan <darren@darrenduncan.net>
wrote:

> On 2022-01-19 4:41 a.m., Dave Mitchell wrote:
> > 1) Another advantage of not populating @_ is that it removes a whole
> bunch
> > of edge cases concerning what happens if @_ is modified during arg
> > processing. In particular things become more complicated if we ever
> > implement named args: this is where the caller does foo(y =>2, x =>1) to
> > call sub foo(:$x, :$y) {} - here the processing of default args etc
> > doesn't follow a simple L-R ordering and it's more likely that @_ could
> > get modified mid-processing.
>
> I know this isn't the main point of what you're saying, but I want to
> address
> the matter of named arguments.
>
> Your example code using "=>" may have just been representative and not
> literal.
>
> But I want to argue that when/if Perl does add native support for named
> parameters/arguments, which I hope it does, I feel that we must use a NEW
> syntax
> to indicate it, and NOT use "=>".
>
> While Perl devs are used to "=>" to indicate fake named
> parameters/arguments,
> the fact remains that this is really just a "fat comma" and a lot of code
> is
> going to break if Perl starts saying that the syntax now maps to named
> parameters.
>
> I propose following an example which is very common in other languages and
> data
> formats, and is also better Huffman coded, which is to use the colon ":"
> to
> indicate named parameters or arguments.
>
> This shouldn't conflict with any other use of the colon that I'm aware of.
>
> So these two things should continue to have the same meaning, and map to 2
> positional parameters:
>
> foo('x', 'y')
> foo(x => 'y')
>
> ... and this would continue to map to a single positional parameter which
> is a
> hashref:
>
> foo({x => 'y'})
>
> Whereas this would map to a named parameter:
>
> foo(x: 'y')
>

It's certainly an interesting idea and I think similar to something that
has been proposed before (not specific to signatures), but for the specific
signature feature, consider that one might want to pass a set of named
parameters directly from aggregate data sources such as: foo(%params) - it
would be a shame to lose this ability as well.

-Dan
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
On 2022-01-21 10:03 p.m., Dan Book wrote:
> On Sat, Jan 22, 2022 at 12:39 AM Darren Duncan wrote:
> But I want to argue that when/if Perl does add native support for named
> parameters/arguments, which I hope it does, I feel that we must use a NEW
> syntax
> to indicate it, and NOT use "=>".
>
> So these two things should continue to have the same meaning, and map to 2
> positional parameters:
>
>    foo('x', 'y')
>    foo(x => 'y')
>
> ... and this would continue to map to a single positional parameter which is a
> hashref:
>
>    foo({x => 'y'})
>
> Whereas this would map to a named parameter:
>
>    foo(x: 'y')
>
> It's certainly an interesting idea and I think similar to something that has
> been proposed before (not specific to signatures), but for the specific
> signature feature, consider that one might want to pass a set of named
> parameters directly from aggregate data sources such as: foo(%params) - it would
> be a shame to lose this ability as well.

Well I expect there would be syntax made available that would allow us to keep
doing the valuable features that worked before.

For backwards compatibility, this would continue to bind to positional
parameters, 2 parameters per hash key-value pair:

foo(%params)

But a new syntax, maybe something like this, could make it instead bind to named
parameters:

foo(:%params)

Or see also how Raku handles this.

I didn't say it in my first post, but something I was thinking about how this
could all be implemented internally...

Internally, the arguments for a sub call are implemented by an ordered
collection, an array or arrayref or essentially as it is now, with 1 collection
element per argument, in the same order as the calling code called the sub, but
each element is now a simple struct which indicates whether it is a positional
or a named argument, and in the case of named, what parameter name it indicates.

Or we can do something else, but the point is that natively an argument list is
represented by something which cleanly represents both positional and named
arguments.

Optionally or if necessary this struct is represented to user code as some new
fundamental simple data type, which then lets Perl code have a way to represent
an argument list as a collection that it can pass around or build or read
dynamically etc similarly to how can with @_ now given how that's an array, and
similarly to how Raku has types such as Capture or whatever for representing
argument lists.

-- Darren Duncan
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
On 2022-01-21 10:37 p.m., Darren Duncan wrote:
> I didn't say it in my first post, but something I was thinking about how this
> could all be implemented internally...
>
> Internally, the arguments for a sub call are implemented by an ordered
> collection, an array or arrayref or essentially as it is now, with 1 collection
> element per argument, in the same order as the calling code called the sub, but
> each element is now a simple struct which indicates whether it is a positional
> or a named argument, and in the case of named, what parameter name it indicates.
>
> Or we can do something else, but the point is that natively an argument list is
> represented by something which cleanly represents both positional and named
> arguments.
>
> Optionally or if necessary this struct is represented to user code as some new
> fundamental simple data type, which then lets Perl code have a way to represent
> an argument list as a collection that it can pass around or build or read
> dynamically etc similarly to how can with @_ now given how that's an array, and
> similarly to how Raku has types such as Capture or whatever for representing
> argument lists.

To further explore the matter of native language support for routines that can
take either positional arguments or named arguments or a combination of both...

Various programming languages do this in different ways and there are a number
of potential options for Perl to adopt.

The common feature of any languages I have looked at is that at least
conceptually they are the same, in that each routine conceptually takes TWO
argument lists, which is 0..N positional parameters represented by an ordered
set such as an array, plus 0..M named parameters represented by an unordered set
of name-value pairs such as a dictionary/hash.

Behind the scenes that representation could be used literally pairing a Perl
array aka @_ with a Perl hash, maybe it could be called %_ if that wasn't
already in use for some other purpose. The pair could be wrapped in some other
type representing a single thing having both kinds of arguments, I believe Raku
calls this combined thing a Capture.

For your information, there is an alternate approach I have chosen to use with
my Muldis Object Notation (MUON) / Muldis Data Language (MDL), which is in
summary to only have named arguments as the only true kind, and to fake
positional arguments in terms of special argument names. Where Raku has
Capture, I have Tuple which is the data type representing argument lists, as
well as all typical concepts of either positional or named tuples.

If Perl were to adopt the same approach as MUON, then it means in effect
entirely swapping out the @_ array for a plain regular Perl hash, and all the
existing Perl operators and routines for hashes would work with it.

How I fake positional arguments with named ones is to use single-character
strings such that the string of just the Unicode codepoint zero, "\x{0}", is the
first positional argument, the string of just codepoint one, "\x{1}", is the
second, and so on.

Strictly speaking that approach has limits, as you can't have more positional
arguments than there are Unicode code points, which if you're being strict is in
one sense about 1.1M, though its much lower as its not valid to use the numbers
from the surrogates, so maybe you get a few thousand.

But practically speaking I designed around the expectation that one wouldn't
actually use more than 32 positional parameters, which corresponds to the main
block of 31 ASCII non-printing control characters plus the space, and assuming
that named parameters would usually just have names with printable characters,
and so code point 32 and up are printable.

In this context, all parameters whether conceptually positional or named can be
expressed in a named form, but the common shorthand exists where positional
syntax implicitly assigns the appropriate "names" left to right, so these are
equivalent:

("\x{0}": 29, "foo": 95)

(29, "foo": 95)

Note that for normalization, a single-character name is treated as a positional
parameter if and only if all other single-character names from zero thru that
one exist in the collection; any time there is a gap, its just treated as
regular named, so for example, this one is treated as having zero positional
parameters:

("\x{1}": 99)

Also it is an error to have an explicit parameter name in the same collection
literal that maps to a positional that is implicitly named, such as this:

(42, "\x{0}": 25)

... similarly to having the same name appear explicitly twice.

Personally I would anticipate Perl would use the array plus hash approach as
that is probably the least surprising, however there are other ways it COULD be
done as I illustrated.

But the implementers should do whatever they feel is best as usual.

-- Darren Duncan
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
TL;DR: the case for naming arguments with "=".

Darren Duncan skribis 2022-01-21 21:38 (-0800):
>But I want to argue that when/if Perl does add native
>support for named parameters/arguments, which I hope it
>does, I feel that we must use a NEW syntax to indicate it,
>and NOT use "=>".

I like the suggestion of leaving "=>" alone (in Raku I find it really annoying that it's used both for creating Pairs and for named arguments, which makes passing a Pair rather cumbersome), but,

>I propose following an example which is very common in
>other languages and data formats, and is also better
>Huffman coded, which is to use the colon ":" to indicate
>named parameters or arguments.

As someone who uses lots of ternaries, I'm not so sure about this specific character. ":" is also involved in decorating sort in another proposal, and is already used for attributes and labels. Larry Wall's "first rule of language redesign", which asserts that "everyone wants the colon", is very true. Because so many people want the colon, it might make sense to pick something else whenever feasible.

>This shouldn't conflict with any other use of the colon that I'm aware of.

Maybe not technically, but visually it's really the same colon as every other colon.

As a counter proposal I suggest "=", because it's nicely consistent with aesthetics of signatures. If named arguments have no sigil and I don't think anyone is currently suggesting giving them any, the distinction between assignment to a variable and to a named parameter should be easy enough. If computed argument names are required, those could be simply quoted, because assignment to a literal string is currently not a thing you can do.

e.g.

# not: f(name => "value");
# not: f(name: "value");

# but:

f(name = "value");
f("positional value", name = "value");
f name = "value";
f "name" = "value";

Run-time computed named argument:
f("$name" = "value");

# unchanged:
f $variable = "positional";

Other languages that use "=" for named arguments include Python, R, Fortran, Julia, Kotlin, Maple, and OpenSCAD.

For the common case of f(arg = $arg, foo = $foo, bar = $bar) where the argument and variable have the same name, I suggest adding prefix "=": f(=$arg, =$foo, =$bar). And, for symmetry, a prefix "=>" for the fat comma equivalent, because that would also be useful when populating hashes and using legacy pseudo-named arguments.
--
Met vriendelijke groet, // Kind regards, // Korajn salutojn,

Juerd Waalboer <juerd@tnx.nl>
TNX
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
On Sun, Jan 23, 2022 at 3:56 PM Juerd Waalboer <juerd@tnx.nl> wrote:

> TL;DR: the case for naming arguments with "=".
>
> Darren Duncan skribis 2022-01-21 21:38 (-0800):
> >But I want to argue that when/if Perl does add native
> >support for named parameters/arguments, which I hope it
> >does, I feel that we must use a NEW syntax to indicate it,
> >and NOT use "=>".
>
> I like the suggestion of leaving "=>" alone (in Raku I find it really
> annoying that it's used both for creating Pairs and for named arguments,
> which makes passing a Pair rather cumbersome), but,
>
> >I propose following an example which is very common in
> >other languages and data formats, and is also better
> >Huffman coded, which is to use the colon ":" to indicate
> >named parameters or arguments.
>
> As someone who uses lots of ternaries, I'm not so sure about this specific
> character. ":" is also involved in decorating sort in another proposal, and
> is already used for attributes and labels. Larry Wall's "first rule of
> language redesign", which asserts that "everyone wants the colon", is very
> true. Because so many people want the colon, it might make sense to pick
> something else whenever feasible.
>
> >This shouldn't conflict with any other use of the colon that I'm aware of.
>
> Maybe not technically, but visually it's really the same colon as every
> other colon.
>
> As a counter proposal I suggest "=", because it's nicely consistent with
> aesthetics of signatures. If named arguments have no sigil and I don't
> think anyone is currently suggesting giving them any, the distinction
> between assignment to a variable and to a named parameter should be easy
> enough. If computed argument names are required, those could be simply
> quoted, because assignment to a literal string is currently not a thing you
> can do.
>
> e.g.
>
> # not: f(name => "value");
> # not: f(name: "value");
>
> # but:
>
> f(name = "value");
> f("positional value", name = "value");
> f name = "value";
> f "name" = "value";
>
> Run-time computed named argument:
> f("$name" = "value");
>
> # unchanged:
> f $variable = "positional";
>
> Other languages that use "=" for named arguments include Python, R,
> Fortran, Julia, Kotlin, Maple, and OpenSCAD.
>
> For the common case of f(arg = $arg, foo = $foo, bar = $bar) where the
> argument and variable have the same name, I suggest adding prefix "=":
> f(=$arg, =$foo, =$bar). And, for symmetry, a prefix "=>" for the fat comma
> equivalent, because that would also be useful when populating hashes and
> using legacy pseudo-named arguments.
>

This syntax is already valid and could be used to assign to an lvalue sub
(though doesn't seem likely to be common).

-Dan
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
On 2022-01-23 12:56 p.m., Juerd Waalboer wrote:
> TL;DR: the case for naming arguments with "=".
>
> Darren Duncan skribis 2022-01-21 21:38 (-0800):
>> But I want to argue that when/if Perl does add native support for named
>> parameters/arguments, which I hope it does, I feel that we must use a NEW
>> syntax to indicate it, and NOT use "=>".
>
> I like the suggestion of leaving "=>" alone (in Raku I find it really annoying
> that it's used both for creating Pairs and for named arguments, which makes
> passing a Pair rather cumbersome), but,

Thank you for the support of my main argument.

>> I propose following an example which is very common in other languages and
>> data formats, and is also better Huffman coded, which is to use the colon ":"
>> to indicate named parameters or arguments.
>
> As someone who uses lots of ternaries, I'm not so sure about this specific
> character. ":" is also involved in decorating sort in another proposal, and is
> already used for attributes and labels. Larry Wall's "first rule of language
> redesign", which asserts that "everyone wants the colon", is very true. Because
> so many people want the colon, it might make sense to pick something else
> whenever feasible.

Well I'm not going to insist on the colon, and your "=" proposal works just as
well for me, and has a lot of precedent.

>> This shouldn't conflict with any other use of the colon that I'm aware of.
>
> Maybe not technically, but visually it's really the same colon as every other
> colon.
>
> As a counter proposal I suggest "=", because it's nicely consistent with
> aesthetics of signatures. If named arguments have no sigil and I don't think
> anyone is currently suggesting giving them any, the distinction between
> assignment to a variable and to a named parameter should be easy enough. If
> computed argument names are required, those could be simply quoted, because
> assignment to a literal string is currently not a thing you can do.

The main problem I see with "=" is that seems to conflict with the fact that
Perl allows assignments to be embedded in the middle of expressions, so how
would a user know that "f($x = $y)" is not an assignment but rather is setting a
named argument.

Actually this raises the very important matter, which is the same issue no
matter what syntax we use to indicate named, in that will Perl support the
argument name coming from an arbitrary expression or variable, or whether only a
hard-coded parameter-name literal is allowed:

my $argname = "x";
f($argname = 42);
f(x = 42);

So are the second 2 lines considered equivalent or is the middle line a
parse/compile error?

I would argue that forbidding the second line can permit some optimizations or
simpler implementations than if the second line was allowed, and I have chosen
to generally forbid it in my MUON/MDL format/language. In particular,
forbidding it means we can be further in the direction of knowing at
parse/compile time whether a particular sub call argument list would be valid
for the sub.

But its a question of what would be considered more Perlish.

> Other languages that use "=" for named arguments include Python, R, Fortran,
> Julia, Kotlin, Maple, and OpenSCAD.
>
> For the common case of f(arg = $arg, foo = $foo, bar = $bar) where the argument
> and variable have the same name, I suggest adding prefix "=":  f(=$arg, =$foo,
> =$bar). And, for symmetry, a prefix "=>" for the fat comma equivalent, because
> that would also be useful when populating hashes and using legacy pseudo-named
> arguments.

Yes, and I would argue in favor of the "=$foo" shorthand as well, whether
spelled that or ":$foo" etc, which Raku introduced me to.

-- Darren Duncan
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
Darren Duncan skribis 2022-01-23 23:03 (-0800):
>The main problem I see with "=" is that seems to conflict
>with the fact that Perl allows assignments to be embedded
>in the middle of expressions, so how would a user know
>that "f($x = $y)" is not an assignment but rather is
>setting a named argument.

In the same way any other syntax would be learned, I think. However, I think that f($x = $y) must remain compatible with existing code, and keep passing the value assigned to $x as a positional argument. The syntax for named argument passing that I described never uses a sigil on the LHS.

As for terminology, isn't setting a named argument also a kind of assignment, though? After all, it's basically a reflection of the subroutine signature in which "=" is also used.

>Actually this raises the very important matter, which is
>the same issue no matter what syntax we use to indicate
>named, in that will Perl support the argument name coming
>from an arbitrary expression or variable, or whether only
>a hard-coded parameter-name literal is allowed:
>
> my $argname = "x";
> f($argname = 42);
> f(x = 42);
>
>So are the second 2 lines considered equivalent or is the
>middle line a parse/compile error?

Neither. In my opinion, the second middle line should remain compatible with current practice in any case.

My suggestion that you're replying to actually covers this issue. I've suggested f("$argname" = 42) for the case where the name of the argument is not hardcoded.

>>For the common case of f(arg = $arg, foo = $foo, bar =
>>$bar) where the argument and variable have the same
>>name, I suggest adding prefix "=":? f(=$arg, =$foo,
>>=$bar). And, for symmetry, a prefix "=>" for the fat
>>comma equivalent, because that would also be useful when
>>populating hashes and using legacy pseudo-named
>>arguments.
>Yes, and I would argue in favor of the "=$foo" shorthand
>as well, whether spelled that or ":$foo" etc, which Raku
>introduced me to.

While I like having a shorthand available, I personally struggle with Raku's use of the colon here, because it's different from the infix operator for named arguments:

# Raku
f :$foo;
f :foo($foo);
f foo => $foo;

These lines are equivalent, even though the colon pair syntax and the fat arrow pair syntax look very different. When Perl gets proper named arguments, I hope it's possible to have the things that do the same look more alike.


--
Met vriendelijke groet, // Kind regards, // Korajn salutojn,

Juerd Waalboer <juerd@tnx.nl>
TNX
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
Dan Book skribis 2022-01-24 0:02 (-0500):
>> # but:
>> f(name = "value");
>> f name = "value";
>This syntax is already valid and could be used to assign to an lvalue sub
>(though doesn't seem likely to be common).

Good point, thanks for pointing that out. I didn't realize lvalue non-method subs were a thing because I've only ever used lvalue methods.

This means that implementing my proposal would break backward compatibility. I don't know how common lvalue subs are and if such breakage would be considered acceptable.

The lvalue sub assignment could remain available in subroutine arguments as:

f name() = "value";
--
Met vriendelijke groet, // Kind regards, // Korajn salutojn,

Juerd Waalboer <juerd@tnx.nl>
TNX
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
I already proposed new syntax (though solving more then just named
arguments), search mailing list for "define meta operator"

Hint to understand my proposal: use mental model where functions/methods
are internally some kind of classes and every call is "create new instance
+ execute run() method".
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
On Fri, Jan 21, 2022 at 09:38:41PM -0800, Darren Duncan wrote:
> I know this isn't the main point of what you're saying, but I want to
> address the matter of named arguments.
>
> Your example code using "=>" may have just been representative and not literal.
>
> But I want to argue that when/if Perl does add native support for named
> parameters/arguments, which I hope it does, I feel that we must use a NEW
> syntax to indicate it, and NOT use "=>".


Just to be clear here. I fully expect that function calls will always
consist of the caller passing a list to the function, and that the
proposed named parameter syntax is just a way of easily processing
adjacent pairs of values in that list. So in:

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

The caller is expected to pass 4 arguments. How the caller does this is up
to the caller. They could do

foo('x', 1, 'y', '2');
@args = qw(y 2 x 1); foo(@args);
foo(y => 2, x => 1);

or even (as I suggest in a separate proposal)

foo(=$x, =$y)

where '=$VARNAME' is syntactic sugar for

('VARNAME', $VARNAME)

and indeed can be used anywhere, not just in argument lists:

@point = (=$x, =$y); # short for ('x', $x, 'y', $y);

If anyone expects sub foo(:$x, :$y) {} to be anything other than the
approximate equivalent of the following, please explain how you would make
it differ.

sub foo {
croak unless @_ == 4; # actually a bit more subtle than that
for (0,2) {
croak unless $_[$_] =~ /^(x|y)$/;
}
my %args = @_;
my ($x, $y) = @args{'x', 'y'};
}

and in particular whether named args can be called with non-name caller
syntax, to allow modules to upgrade to signatures without affecting
callers.


--
I thought I was wrong once, but I was mistaken.
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
Dave, now that you've explained this, your proposal does seem by far the
simplest and backwards compatible option for named parameters, versus "real"
named parameters that I mentioned. -- Darren Duncan

On 2022-01-31 12:50 p.m., Dave Mitchell wrote:
> On Fri, Jan 21, 2022 at 09:38:41PM -0800, Darren Duncan wrote:
>> I know this isn't the main point of what you're saying, but I want to
>> address the matter of named arguments.
>>
>> Your example code using "=>" may have just been representative and not literal.
>>
>> But I want to argue that when/if Perl does add native support for named
>> parameters/arguments, which I hope it does, I feel that we must use a NEW
>> syntax to indicate it, and NOT use "=>".
>
>
> Just to be clear here. I fully expect that function calls will always
> consist of the caller passing a list to the function, and that the
> proposed named parameter syntax is just a way of easily processing
> adjacent pairs of values in that list. So in:
>
> sub foo(:$x, :$y) { ... }
>
> The caller is expected to pass 4 arguments. How the caller does this is up
> to the caller. They could do
>
> foo('x', 1, 'y', '2');
> @args = qw(y 2 x 1); foo(@args);
> foo(y => 2, x => 1);
>
> or even (as I suggest in a separate proposal)
>
> foo(=$x, =$y)
>
> where '=$VARNAME' is syntactic sugar for
>
> ('VARNAME', $VARNAME)
>
> and indeed can be used anywhere, not just in argument lists:
>
> @point = (=$x, =$y); # short for ('x', $x, 'y', $y);
>
> If anyone expects sub foo(:$x, :$y) {} to be anything other than the
> approximate equivalent of the following, please explain how you would make
> it differ.
>
> sub foo {
> croak unless @_ == 4; # actually a bit more subtle than that
> for (0,2) {
> croak unless $_[$_] =~ /^(x|y)$/;
> }
> my %args = @_;
> my ($x, $y) = @args{'x', 'y'};
> }
>
> and in particular whether named args can be called with non-name caller
> syntax, to allow modules to upgrade to signatures without affecting
> callers.
>
>
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
Reviving an old discussion ...

On Mon, Jan 31, 2022 at 9:50 PM Dave Mitchell <davem@iabyn.com> wrote:

> Just to be clear here. I fully expect that function calls will always
> consist of the caller passing a list to the function, and that the
> proposed named parameter syntax is just a way of easily processing
> adjacent pairs of values in that list. So in:
>
> sub foo(:$x, :$y) { ... }
>
> The caller is expected to pass 4 arguments. How the caller does this is up
> to the caller. They could do
>
> foo('x', 1, 'y', '2');
>

Since arrays and hashes are flattened into a list, it seems that someone
might do sub foo(:@bar) {...} and get surprising results. Either it doesn't
do what they expect, or it's a syntax error. If named arguments can only
use scalar values, why not drop the sigil?

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

Best,
Curtis "Ovid" Poe
--
CTO, All Around the World
World-class software development and consulting
https://allaroundtheworld.fr/
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
On Tue, Oct 04, 2022 at 03:40:59PM +0200, Ovid wrote:
> Reviving an old discussion ...
>
> On Mon, Jan 31, 2022 at 9:50 PM Dave Mitchell <davem@iabyn.com> wrote:
>
> > Just to be clear here. I fully expect that function calls will always
> > consist of the caller passing a list to the function, and that the
> > proposed named parameter syntax is just a way of easily processing
> > adjacent pairs of values in that list. So in:
> >
> > sub foo(:$x, :$y) { ... }
> >
> > The caller is expected to pass 4 arguments. How the caller does this is up
> > to the caller. They could do
> >
> > foo('x', 1, 'y', '2');
> >
>
> Since arrays and hashes are flattened into a list, it seems that someone
> might do sub foo(:@bar) {...} and get surprising results. Either it doesn't
> do what they expect, or it's a syntax error. If named arguments can only
> use scalar values, why not drop the sigil?
>
> sub foo (:x, :y) { ... }

I'd expect :@bar to be a syntax error. But note that in a separate
proposal, a \@ary parameter auto-dereferences and aliases a passed array
ref, as in

sub foo(\@numbers) { say "@numbers" }
foo([1,2,3]); # prints "1 2 3"

This can be combined separately with named parameters, giving

sub foo(\:@numbers) { say "@numbers" }
foo("numbers => [1,2,3]); # prints "1 2 3"

--
"Strange women lying in ponds distributing swords is no basis for a system
of government. Supreme executive power derives from a mandate from the
masses, not from some farcical aquatic ceremony."
-- Dennis, "Monty Python and the Holy Grail"
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
On Fri, Oct 7, 2022 at 11:42 AM Dave Mitchell <davem@iabyn.com> wrote:

> I'd expect :@bar to be a syntax error. But note that in a separate
> proposal, a \@ary parameter auto-dereferences and aliases a passed array
> ref, as in
>
> sub foo(\@numbers) { say "@numbers" }
> foo([1,2,3]); # prints "1 2 3"
>
> This can be combined separately with named parameters, giving
>
> sub foo(\:@numbers) { say "@numbers" }
> foo("numbers => [1,2,3]); # prints "1 2 3"
>

Is the double quote in front of numbers a typo or a syntactical feature?

Best,
Curtis "Ovid" Poe
--
CTO, All Around the World
World-class software development and consulting
https://allaroundtheworld.fr/
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
On Fri, Oct 07, 2022 at 05:04:40PM +0200, Ovid wrote:
> Is the double quote in front of numbers a typo or a syntactical feature?

Typo!

--
A walk of a thousand miles begins with a single step...
then continues for another 1,999,999 or so.
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
On Fri, 7 Oct 2022 10:42:23 +0100
Dave Mitchell <davem@iabyn.com> wrote:

> I'd expect :@bar to be a syntax error. But note that in a separate
> proposal, a \@ary parameter auto-dereferences and aliases a passed
> array ref, as in
>
> sub foo(\@numbers) { say "@numbers" }
> foo([1,2,3]); # prints "1 2 3"
>
> This can be combined separately with named parameters, giving
>
> sub foo(\:@numbers) { say "@numbers" }
> foo("numbers => [1,2,3]); # prints "1 2 3"

My thoughts:

sub named(:$x, :$y) # looks nice

sub no_slurpy(:@nums) # should be banned

sub dereffed(\@values) # again looks nice

However,

sub named_deref(:\@x) # I think I'd prefer this spelling

To my eye, `:\@arr` looks and feels a bit better than `\:@arr` does.
Since we're banning `:@arr`, we learn to avoid a colon next to an at or
percent sign. It also fits better with what you'd pass in from the
callsite

my $result = named_deref\@values_for_x);

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
On Fri, 7 Oct 2022 17:04:33 +0100
"Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:

> my $result = named_deref\@values_for_x);

Ugh, I of course meant

my $result = named_deref(\@values_for_x);


.oO( Come on email - Twitter added an Edit button this week, when you
gonna catch up? ;) )

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
On Fri, Oct 7, 2022 at 6:04 PM Paul "LeoNerd" Evans <leonerd@leonerd.org.uk>
wrote:

> > I'd expect :@bar to be a syntax error. But note that in a separate
> > proposal, a \@ary parameter auto-dereferences and aliases a passed
> > array ref, as in
> >
> > sub foo(\@numbers) { say "@numbers" }
> > foo([1,2,3]); # prints "1 2 3"
> >
> > This can be combined separately with named parameters, giving
> >
> > sub foo(\:@numbers) { say "@numbers" }
> > foo("numbers => [1,2,3]); # prints "1 2 3"
>
> My thoughts:
>
> sub named(:$x, :$y) # looks nice
>
> sub no_slurpy(:@nums) # should be banned
>
> sub dereffed(\@values) # again looks nice
>
> However,
>
> sub named_deref(:\@x) # I think I'd prefer this spelling
>
> To my eye, `:\@arr` looks and feels a bit better than `\:@arr` does.
> Since we're banning `:@arr`, we learn to avoid a colon next to an at or
> percent sign. It also fits better with what you'd pass in from the
> callsite
>
> my $result = named_deref\@values_for_x);


First, I think that \:@foo is troublesome because then we're going to have
to explain, for named parameters, that you prefix them with a colon except
when ... and having to remember multiple rules leads to confusion. So
:\@foo seems
cleaner because it leads to single, clear rule:

"Rule 1: Name parameters always begin with a colon."

That seems unambiguous.

That being said, :\@foo compounds Perl's reputation for linenoise. Can we
come up with a rule to avoid this? My first thought is:

"Rule 2: named parameters are scalars, with the scalar constrained to an
array or hash reference, if needed."

With that, no need to include extra punctuation:

sub foo( $bar, :@baz, :%quux ) { ... }
# Only legally called via variants of:
foo( bar => $bar, baz => \@array, quux => \%hash );

Of course, bar can be an aref or href. Only baz and quux are constrained. I
think this fits quite well with Perl's current semantics.

Thus, you only have two rules for named parameters and (I think) they're
consistent. It also removes the gross :\% or \:% in the signature.

I wonder if later we can extend the calling syntax to use a leading colon
for consistency:

foo( :$bar, :@baz, :%quux );

Each argument is passed to their corresponding parameter without
list flattening. (I assume they're not aliased, but copying could be
expensive and we don't have copy-on-write).

That being said, it means you've coupled the argument names to the
parameter names. I don't know if that's a bad thing, but it might make life
painful for a maintainer who wants to change a variable name to be more
descriptive, but leave the name of the key unchanged (so as to not alter
the interface). But even that can be deal with:

sub foo( $bar, :@baz, :%quux ) {
my @useful_name = @baz;
...
}

Best,
Curtis "Ovid" Poe
--
CTO, All Around the World
World-class software development and consulting
https://allaroundtheworld.fr/
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
On Sat, Oct 8, 2022 at 3:18 PM Ovid <curtis.poe@gmail.com> wrote:

> That being said, :\@foo compounds Perl's reputation for linenoise. Can we
> come up with a rule to avoid this? My first thought is:
>
> "Rule 2: named parameters are scalars, with the scalar constrained to an
> array or hash reference, if needed."
>
>
Ouch. I rewrote this email after I rethought things in terms of
non-flattening variables instead of references, but I forgot to fix rule 2.

"Rule 2: named parameters correspond to their named arguments without
flattening, unless explicit name/value pairs are used."

That leads to two calling conventions:

foo( bar => $bar, baz => \@baz, quux => \%quux );
# versus
foo( :$bar, :@baz, :%quux );

In this case, TIMTOWTDI seems confusing because the second syntax seems
much cleaner (and concise) to me, but we'd still have to support the older
syntax. Thus, we still need to have an exception to the rule. I am not sure
that's avoidable, but we'd have the consistency of a leading colon for both
arguments and parameters.

Best,
Curtis "Ovid" Poe
--
CTO, All Around the World
World-class software development and consulting
https://allaroundtheworld.fr/
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
Please differentiate between named argument function call syntax and named
parameter extended signatures.

What we should answer first is want we want:
- do we want to limit arguments to $ sigil (+ slurpy) ?
- do we want freedom of function user to choose how to call function? (for
examples functions in
Postgresql, C#, Kotlin, Python)
- do we want extended constraints? (eg: $login and $oauth are mutually
exclusive, $password must be specified when $login exists)
- ...

Best regards,
Brano
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
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.
Re: Named argument syntax (was Re: PSC #049 2022-01-07) [ In reply to ]
On Sat, Oct 08, 2022 at 07:13:17PM +0200, Branislav Zahradn?k wrote:
> Please differentiate between named argument function call syntax and named
> parameter extended signatures.

I think I covered that in my email from an hour ago.

> What we should answer first is want we want:
> - do we want to limit arguments to $ sigil (+ slurpy) ?

Arguments are an arbitrary list passed to a function. It is up to the
coder of that function how they precess those arguments, assign values to
local variables, check for errors etc. They may use the traditional
approach of directly accessing @_, or use the new signature feature
to allow the perl internals to more efficiently do some of that processing
in an automated fashion.

> - do we want freedom of function user to choose how to call function? (for
> examples functions in
> Postgresql, C#, Kotlin, Python)

I have no idea what any of those languages do. But in general, the perl
philosophy is that a user can construct the arguments to a function however
they chose:

foo(1,2,3,4);
@a = (2,3); foo (1, @a,4);
foo((1,$cond ? (2,3) : (-2,-3)), 4);
etc.

And this would be unaffected by function's signature, which isn't examined
by perl at the call site at compile-time, nor run-time. If you want
something like that, then that's what prototypes are for.

> - do we want extended constraints? (eg: $login and $oauth are mutually
> exclusive, $password must be specified when $login exists)

I've never considered constraints that affect more than a single
parameter. I have no strong opinion on whether they would be a good idea
or not. I would likely want to see some proposed syntax/semantics before
forming an opinion,

--
The crew of the Enterprise encounter an alien life form which is
surprisingly neither humanoid nor made from pure energy.
-- Things That Never Happen in "Star Trek" #22