Mailing List Archive

RFC: Multiple-alias syntax for for
So, the plan for discussing the proposed RFC process was to feed an idea
through it, and see how we get from idea to RFC to implementation.
(Assuming that we don't reject the idea.)

About two months ago Rik had mentioned to me the idea of implementing this
(currently illegal) syntax to iterate over hashes:

for my ($key, $value) (%hash) { ... }

which isn't actually hash specific - it generalises to N-at-a-time over any
list.

I figured that the *runtime* part probably wasn't that hard, so had a crack
implementing that, assuming that I'd get help with the parser part once I
had an idea how the runtime and the optree needed to be. Except that I
didn't get stuck, and got to a complete implementation, which has been
pushed somewhere public for 6 weeks now.

( somewhere reachable in 6 clicks from https://github.com/Perl/RFCs )

So, if you have the time and skills, please try implementing something else
that would improve Perl, as re-implementing this is duplication of effort.



By chance, I started on this a couple of days before KES777 submitted
https://github.com/Perl/perl5/issues/18744
and in turn, that links to a message from Dan Brook in 2017 proposing it:
https://www.nntp.perl.org/group/perl.perl5.porters/2017/03/msg243848.html


So, rather than start on the RFC by "faking" an "idea" mail from Rik, I'll
take the genuine item from Dan:

On Fri, Mar 31, 2017 at 06:39:59PM -0400, Dan Book wrote:
> The "each" function is generally discouraged due to implementation details,
> but is still the most "pretty" and concise way to write such a loop:
>
> while (my ($key, $value) = each %hash) { ... }
>
> A possible alternative to this would be a syntax to alias multiple items
> per iteration in a for/foreach loop.
>
> foreach my ($key, $value) (%hash) { ... }
>
> This could be generalized as a "bundler", in other words to alias a number
> of elements from the list equal to the number of variables specified. Such
> as:
>
> foreach my ($foo, $bar, $baz) (@array) { # $foo, $bar, and $baz are the
> next three elements of @array, or undef if overflowed
>
> I can think of one syntactical issue presently: "foreach ($foo, $bar)"
> without the "my" is already valid syntax so would be difficult to
> disambiguate without looking for the second () denoting the list to iterate
> through.
>
> Thoughts?
>
> -Dan


This arrives here:

idea
|
v
mail p5p
|
better | rejected
on <-------?-------> with
CPAN | reasoning
v
Draft RFC
"we think this idea is worth exploring"
(Help us figure out how this will work)


For this idea, "we think this idea is worth exploring" applies, so we need
a draft.


So

1) I need to assign an ID.

Question - do I start at 0001, or keep low numbers for "something special"?
I'm guessing "start at 0001"


2) Format - PSC had thought Markdown, as many places can render it.

However,

a) github itself can render Pod. Is it the only git hosting service that can?
b) I've already found that my local markdown renderer and github disagree
about nested lists, which is annoying - how many other bugs will I hit?
c) Pod doesn't do tables, but plain markdown doesn't either.
github extended markdown with tables, but
i) How many other markdown implementations follow them?
ii) Are there alternative competing "table" dialects of Markdown?
d) I'm missing =cut


3) Who is the formal "Author" of this RFC. Does Dan want to be named?
Currently I seem to be ghost writing it, but if I become the author,
then someone else needs to take over as sponsor?
Should the copyright be Dan, and 2017?


Appended is my first draft, as if I'd only read Dan's mail.

I figure that as there has already been some discussion on github in 2021
and p5p in 2017, I should act as if that came in reply to this message,
and try taking this from here, by filling in some of the other sections.

Nicholas Clark



# Preamble

Author:
Sponsor: Nicholas Clark <nick@ccl4.org>
ID: 0001
Status: Draft
Title: Multiple-alias syntax for foreach

# Abstract

Implement the currently illegal syntax `for my ($key, $value) (%hash) { ... }` to act as two-at-a-time iteration over hashes. This approach is not specific to hashes - it generalises to n-at-a-time over any list.

# Motivation

The `each` function is generally discouraged due to implementation details, but is still the most "pretty" and concise way to write such a loop:

while (my ($key, $value) = each %hash) { ... }

An alternative to this would be a syntax to alias multiple items per iteration in a `for` loop.

for my ($key, $value) (%hash) { ... }

This generalizes as a "bundler" - to alias a number of elements from the list equal to the number of variables specified. Such as:

for my ($foo, $bar, $baz) (@array) {
# $foo, $bar, and $baz are the next three elements of @array,
# or undef if overflowed

# Rationale

The existing syntax to iterate over the keys and values of a hash:

while (my ($key, $value) = each %hash) { ... }

suffers from several problems

* For correctness it assumes that the internal state of the hash being "clean" - to be robust one should reset the iterator first with `keys %hash;` in void context
* It's hard to teach to beginners - to understand what is going on here one needs to know
- list assignment
- empty lists are false; non-empty lists are true
- that the hash holds an internal iterator
* You can't modify the hash inside the loop without confusing the iterator

The proposed syntax solves all of these.

# Specification

# Backwards Compatibility

# Security Implications

# Examples

*FIXME* - are there useful examples that aren't in the Motivation/

# Prototype Implementation

"Here's one I made earlier" applies - we already have one written, so there's no need to duplicate work

# Rejected Ideas

# Open Issues


# Copyright

Copyright (C) 2021, Nicholas Clark

This document and code and documentation within it may be used, redistributed and/or modified under the same terms as Perl itself.
Re: RFC: Multiple-alias syntax for for [ In reply to ]
This is a great example.

I support this syntax 100%. Well done.

On 6/8/2021 4:20 AM, Nicholas Clark wrote:
> So, the plan for discussing the proposed RFC process was to feed an idea
> through it, and see how we get from idea to RFC to implementation.
> (Assuming that we don't reject the idea.)
>
> About two months ago Rik had mentioned to me the idea of implementing this
> (currently illegal) syntax to iterate over hashes:
>
> for my ($key, $value) (%hash) { ... }
>
> which isn't actually hash specific - it generalises to N-at-a-time over any
> list.
>
> I figured that the *runtime* part probably wasn't that hard, so had a crack
> implementing that, assuming that I'd get help with the parser part once I
> had an idea how the runtime and the optree needed to be. Except that I
> didn't get stuck, and got to a complete implementation, which has been
> pushed somewhere public for 6 weeks now.
>
> ( somewhere reachable in 6 clicks from https://github.com/Perl/RFCs )
>
> So, if you have the time and skills, please try implementing something else
> that would improve Perl, as re-implementing this is duplication of effort.
>
>
>
> By chance, I started on this a couple of days before KES777 submitted
> https://github.com/Perl/perl5/issues/18744
> and in turn, that links to a message from Dan Brook in 2017 proposing it:
> https://www.nntp.perl.org/group/perl.perl5.porters/2017/03/msg243848.html
>
>
> So, rather than start on the RFC by "faking" an "idea" mail from Rik, I'll
> take the genuine item from Dan:
>
> On Fri, Mar 31, 2017 at 06:39:59PM -0400, Dan Book wrote:
>> The "each" function is generally discouraged due to implementation details,
>> but is still the most "pretty" and concise way to write such a loop:
>>
>> while (my ($key, $value) = each %hash) { ... }
>>
>> A possible alternative to this would be a syntax to alias multiple items
>> per iteration in a for/foreach loop.
>>
>> foreach my ($key, $value) (%hash) { ... }
>>
>> This could be generalized as a "bundler", in other words to alias a number
>> of elements from the list equal to the number of variables specified. Such
>> as:
>>
>> foreach my ($foo, $bar, $baz) (@array) { # $foo, $bar, and $baz are the
>> next three elements of @array, or undef if overflowed
>>
>> I can think of one syntactical issue presently: "foreach ($foo, $bar)"
>> without the "my" is already valid syntax so would be difficult to
>> disambiguate without looking for the second () denoting the list to iterate
>> through.
>>
>> Thoughts?
>>
>> -Dan
>
> This arrives here:
>
> idea
> |
> v
> mail p5p
> |
> better | rejected
> on <-------?-------> with
> CPAN | reasoning
> v
> Draft RFC
> "we think this idea is worth exploring"
> (Help us figure out how this will work)
>
>
> For this idea, "we think this idea is worth exploring" applies, so we need
> a draft.
>
>
> So
>
> 1) I need to assign an ID.
>
> Question - do I start at 0001, or keep low numbers for "something special"?
> I'm guessing "start at 0001"
>
>
> 2) Format - PSC had thought Markdown, as many places can render it.
>
> However,
>
> a) github itself can render Pod. Is it the only git hosting service that can?
> b) I've already found that my local markdown renderer and github disagree
> about nested lists, which is annoying - how many other bugs will I hit?
> c) Pod doesn't do tables, but plain markdown doesn't either.
> github extended markdown with tables, but
> i) How many other markdown implementations follow them?
> ii) Are there alternative competing "table" dialects of Markdown?
> d) I'm missing =cut
>
>
> 3) Who is the formal "Author" of this RFC. Does Dan want to be named?
> Currently I seem to be ghost writing it, but if I become the author,
> then someone else needs to take over as sponsor?
> Should the copyright be Dan, and 2017?
>
>
> Appended is my first draft, as if I'd only read Dan's mail.
>
> I figure that as there has already been some discussion on github in 2021
> and p5p in 2017, I should act as if that came in reply to this message,
> and try taking this from here, by filling in some of the other sections.
>
> Nicholas Clark
>
>
>
> # Preamble
>
> Author:
> Sponsor: Nicholas Clark <nick@ccl4.org>
> ID: 0001
> Status: Draft
> Title: Multiple-alias syntax for foreach
>
> # Abstract
>
> Implement the currently illegal syntax `for my ($key, $value) (%hash) { ... }` to act as two-at-a-time iteration over hashes. This approach is not specific to hashes - it generalises to n-at-a-time over any list.
>
> # Motivation
>
> The `each` function is generally discouraged due to implementation details, but is still the most "pretty" and concise way to write such a loop:
>
> while (my ($key, $value) = each %hash) { ... }
>
> An alternative to this would be a syntax to alias multiple items per iteration in a `for` loop.
>
> for my ($key, $value) (%hash) { ... }
>
> This generalizes as a "bundler" - to alias a number of elements from the list equal to the number of variables specified. Such as:
>
> for my ($foo, $bar, $baz) (@array) {
> # $foo, $bar, and $baz are the next three elements of @array,
> # or undef if overflowed
>
> # Rationale
>
> The existing syntax to iterate over the keys and values of a hash:
>
> while (my ($key, $value) = each %hash) { ... }
>
> suffers from several problems
>
> * For correctness it assumes that the internal state of the hash being "clean" - to be robust one should reset the iterator first with `keys %hash;` in void context
> * It's hard to teach to beginners - to understand what is going on here one needs to know
> - list assignment
> - empty lists are false; non-empty lists are true
> - that the hash holds an internal iterator
> * You can't modify the hash inside the loop without confusing the iterator
>
> The proposed syntax solves all of these.
>
> # Specification
>
> # Backwards Compatibility
>
> # Security Implications
>
> # Examples
>
> *FIXME* - are there useful examples that aren't in the Motivation/
>
> # Prototype Implementation
>
> "Here's one I made earlier" applies - we already have one written, so there's no need to duplicate work
>
> # Rejected Ideas
>
> # Open Issues
>
>
> # Copyright
>
> Copyright (C) 2021, Nicholas Clark
>
> This document and code and documentation within it may be used, redistributed and/or modified under the same terms as Perl itself.
>
Re: RFC: Multiple-alias syntax for for [ In reply to ]
This is actually something I prototyped a few years ago with a source
filter, I kept meaning to get around to trying to make a parser change/etc.
that actually does it in a sane way but have never had the time to properly
learn how to do it inside perl.

It was done with Keyword::Simple, and you can see it here:
https://perl.bot/p/cxj1ay

On Tue, Jun 8, 2021 at 7:21 AM Nicholas Clark <nick@ccl4.org> wrote:

> So, the plan for discussing the proposed RFC process was to feed an idea
> through it, and see how we get from idea to RFC to implementation.
> (Assuming that we don't reject the idea.)
>
> About two months ago Rik had mentioned to me the idea of implementing this
> (currently illegal) syntax to iterate over hashes:
>
> for my ($key, $value) (%hash) { ... }
>
> which isn't actually hash specific - it generalises to N-at-a-time over any
> list.
>
> I figured that the *runtime* part probably wasn't that hard, so had a crack
> implementing that, assuming that I'd get help with the parser part once I
> had an idea how the runtime and the optree needed to be. Except that I
> didn't get stuck, and got to a complete implementation, which has been
> pushed somewhere public for 6 weeks now.
>
> ( somewhere reachable in 6 clicks from https://github.com/Perl/RFCs )
>
> So, if you have the time and skills, please try implementing something else
> that would improve Perl, as re-implementing this is duplication of effort.
>
>
>
> By chance, I started on this a couple of days before KES777 submitted
> https://github.com/Perl/perl5/issues/18744
> and in turn, that links to a message from Dan Brook in 2017 proposing it:
> https://www.nntp.perl.org/group/perl.perl5.porters/2017/03/msg243848.html
>
>
> So, rather than start on the RFC by "faking" an "idea" mail from Rik, I'll
> take the genuine item from Dan:
>
> On Fri, Mar 31, 2017 at 06:39:59PM -0400, Dan Book wrote:
> > The "each" function is generally discouraged due to implementation
> details,
> > but is still the most "pretty" and concise way to write such a loop:
> >
> > while (my ($key, $value) = each %hash) { ... }
> >
> > A possible alternative to this would be a syntax to alias multiple items
> > per iteration in a for/foreach loop.
> >
> > foreach my ($key, $value) (%hash) { ... }
> >
> > This could be generalized as a "bundler", in other words to alias a
> number
> > of elements from the list equal to the number of variables specified.
> Such
> > as:
> >
> > foreach my ($foo, $bar, $baz) (@array) { # $foo, $bar, and $baz are the
> > next three elements of @array, or undef if overflowed
> >
> > I can think of one syntactical issue presently: "foreach ($foo, $bar)"
> > without the "my" is already valid syntax so would be difficult to
> > disambiguate without looking for the second () denoting the list to
> iterate
> > through.
> >
> > Thoughts?
> >
> > -Dan
>
>
> This arrives here:
>
> idea
> |
> v
> mail p5p
> |
> better | rejected
> on <-------?-------> with
> CPAN | reasoning
> v
> Draft RFC
> "we think this idea is worth exploring"
> (Help us figure out how this will work)
>
>
> For this idea, "we think this idea is worth exploring" applies, so we need
> a draft.
>
>
> So
>
> 1) I need to assign an ID.
>
> Question - do I start at 0001, or keep low numbers for "something special"?
> I'm guessing "start at 0001"
>
>
> 2) Format - PSC had thought Markdown, as many places can render it.
>
> However,
>
> a) github itself can render Pod. Is it the only git hosting service that
> can?
> b) I've already found that my local markdown renderer and github disagree
> about nested lists, which is annoying - how many other bugs will I hit?
> c) Pod doesn't do tables, but plain markdown doesn't either.
> github extended markdown with tables, but
> i) How many other markdown implementations follow them?
> ii) Are there alternative competing "table" dialects of Markdown?
> d) I'm missing =cut
>
>
> 3) Who is the formal "Author" of this RFC. Does Dan want to be named?
> Currently I seem to be ghost writing it, but if I become the author,
> then someone else needs to take over as sponsor?
> Should the copyright be Dan, and 2017?
>
>
> Appended is my first draft, as if I'd only read Dan's mail.
>
> I figure that as there has already been some discussion on github in 2021
> and p5p in 2017, I should act as if that came in reply to this message,
> and try taking this from here, by filling in some of the other sections.
>
> Nicholas Clark
>
>
>
> # Preamble
>
> Author:
> Sponsor: Nicholas Clark <nick@ccl4.org>
> ID: 0001
> Status: Draft
> Title: Multiple-alias syntax for foreach
>
> # Abstract
>
> Implement the currently illegal syntax `for my ($key, $value) (%hash) {
> ... }` to act as two-at-a-time iteration over hashes. This approach is not
> specific to hashes - it generalises to n-at-a-time over any list.
>
> # Motivation
>
> The `each` function is generally discouraged due to implementation
> details, but is still the most "pretty" and concise way to write such a
> loop:
>
> while (my ($key, $value) = each %hash) { ... }
>
> An alternative to this would be a syntax to alias multiple items per
> iteration in a `for` loop.
>
> for my ($key, $value) (%hash) { ... }
>
> This generalizes as a "bundler" - to alias a number of elements from the
> list equal to the number of variables specified. Such as:
>
> for my ($foo, $bar, $baz) (@array) {
> # $foo, $bar, and $baz are the next three elements of @array,
> # or undef if overflowed
>
> # Rationale
>
> The existing syntax to iterate over the keys and values of a hash:
>
> while (my ($key, $value) = each %hash) { ... }
>
> suffers from several problems
>
> * For correctness it assumes that the internal state of the hash being
> "clean" - to be robust one should reset the iterator first with `keys
> %hash;` in void context
> * It's hard to teach to beginners - to understand what is going on here
> one needs to know
> - list assignment
> - empty lists are false; non-empty lists are true
> - that the hash holds an internal iterator
> * You can't modify the hash inside the loop without confusing the iterator
>
> The proposed syntax solves all of these.
>
> # Specification
>
> # Backwards Compatibility
>
> # Security Implications
>
> # Examples
>
> *FIXME* - are there useful examples that aren't in the Motivation/
>
> # Prototype Implementation
>
> "Here's one I made earlier" applies - we already have one written, so
> there's no need to duplicate work
>
> # Rejected Ideas
>
> # Open Issues
>
>
> # Copyright
>
> Copyright (C) 2021, Nicholas Clark
>
> This document and code and documentation within it may be used,
> redistributed and/or modified under the same terms as Perl itself.
>
Re: RFC: Multiple-alias syntax for for [ In reply to ]
Sorry about that, I recovered the wrong old paste, this is the right one:
https://perl.bot/p/8ax2rw

On Tue, Jun 8, 2021 at 1:49 PM Ryan Voots <simcop2387@simcop2387.info>
wrote:

> This is actually something I prototyped a few years ago with a source
> filter, I kept meaning to get around to trying to make a parser change/etc.
> that actually does it in a sane way but have never had the time to properly
> learn how to do it inside perl.
>
> It was done with Keyword::Simple, and you can see it here:
> https://perl.bot/p/cxj1ay
>
> On Tue, Jun 8, 2021 at 7:21 AM Nicholas Clark <nick@ccl4.org> wrote:
>
>> So, the plan for discussing the proposed RFC process was to feed an idea
>> through it, and see how we get from idea to RFC to implementation.
>> (Assuming that we don't reject the idea.)
>>
>> About two months ago Rik had mentioned to me the idea of implementing this
>> (currently illegal) syntax to iterate over hashes:
>>
>> for my ($key, $value) (%hash) { ... }
>>
>> which isn't actually hash specific - it generalises to N-at-a-time over
>> any
>> list.
>>
>> I figured that the *runtime* part probably wasn't that hard, so had a
>> crack
>> implementing that, assuming that I'd get help with the parser part once I
>> had an idea how the runtime and the optree needed to be. Except that I
>> didn't get stuck, and got to a complete implementation, which has been
>> pushed somewhere public for 6 weeks now.
>>
>> ( somewhere reachable in 6 clicks from https://github.com/Perl/RFCs )
>>
>> So, if you have the time and skills, please try implementing something
>> else
>> that would improve Perl, as re-implementing this is duplication of effort.
>>
>>
>>
>> By chance, I started on this a couple of days before KES777 submitted
>> https://github.com/Perl/perl5/issues/18744
>> and in turn, that links to a message from Dan Brook in 2017 proposing it:
>> https://www.nntp.perl.org/group/perl.perl5.porters/2017/03/msg243848.html
>>
>>
>> So, rather than start on the RFC by "faking" an "idea" mail from Rik, I'll
>> take the genuine item from Dan:
>>
>> On Fri, Mar 31, 2017 at 06:39:59PM -0400, Dan Book wrote:
>> > The "each" function is generally discouraged due to implementation
>> details,
>> > but is still the most "pretty" and concise way to write such a loop:
>> >
>> > while (my ($key, $value) = each %hash) { ... }
>> >
>> > A possible alternative to this would be a syntax to alias multiple items
>> > per iteration in a for/foreach loop.
>> >
>> > foreach my ($key, $value) (%hash) { ... }
>> >
>> > This could be generalized as a "bundler", in other words to alias a
>> number
>> > of elements from the list equal to the number of variables specified.
>> Such
>> > as:
>> >
>> > foreach my ($foo, $bar, $baz) (@array) { # $foo, $bar, and $baz are the
>> > next three elements of @array, or undef if overflowed
>> >
>> > I can think of one syntactical issue presently: "foreach ($foo, $bar)"
>> > without the "my" is already valid syntax so would be difficult to
>> > disambiguate without looking for the second () denoting the list to
>> iterate
>> > through.
>> >
>> > Thoughts?
>> >
>> > -Dan
>>
>>
>> This arrives here:
>>
>> idea
>> |
>> v
>> mail p5p
>> |
>> better | rejected
>> on <-------?-------> with
>> CPAN | reasoning
>> v
>> Draft RFC
>> "we think this idea is worth exploring"
>> (Help us figure out how this will work)
>>
>>
>> For this idea, "we think this idea is worth exploring" applies, so we need
>> a draft.
>>
>>
>> So
>>
>> 1) I need to assign an ID.
>>
>> Question - do I start at 0001, or keep low numbers for "something
>> special"?
>> I'm guessing "start at 0001"
>>
>>
>> 2) Format - PSC had thought Markdown, as many places can render it.
>>
>> However,
>>
>> a) github itself can render Pod. Is it the only git hosting service that
>> can?
>> b) I've already found that my local markdown renderer and github disagree
>> about nested lists, which is annoying - how many other bugs will I hit?
>> c) Pod doesn't do tables, but plain markdown doesn't either.
>> github extended markdown with tables, but
>> i) How many other markdown implementations follow them?
>> ii) Are there alternative competing "table" dialects of Markdown?
>> d) I'm missing =cut
>>
>>
>> 3) Who is the formal "Author" of this RFC. Does Dan want to be named?
>> Currently I seem to be ghost writing it, but if I become the author,
>> then someone else needs to take over as sponsor?
>> Should the copyright be Dan, and 2017?
>>
>>
>> Appended is my first draft, as if I'd only read Dan's mail.
>>
>> I figure that as there has already been some discussion on github in 2021
>> and p5p in 2017, I should act as if that came in reply to this message,
>> and try taking this from here, by filling in some of the other sections.
>>
>> Nicholas Clark
>>
>>
>>
>> # Preamble
>>
>> Author:
>> Sponsor: Nicholas Clark <nick@ccl4.org>
>> ID: 0001
>> Status: Draft
>> Title: Multiple-alias syntax for foreach
>>
>> # Abstract
>>
>> Implement the currently illegal syntax `for my ($key, $value) (%hash) {
>> ... }` to act as two-at-a-time iteration over hashes. This approach is not
>> specific to hashes - it generalises to n-at-a-time over any list.
>>
>> # Motivation
>>
>> The `each` function is generally discouraged due to implementation
>> details, but is still the most "pretty" and concise way to write such a
>> loop:
>>
>> while (my ($key, $value) = each %hash) { ... }
>>
>> An alternative to this would be a syntax to alias multiple items per
>> iteration in a `for` loop.
>>
>> for my ($key, $value) (%hash) { ... }
>>
>> This generalizes as a "bundler" - to alias a number of elements from the
>> list equal to the number of variables specified. Such as:
>>
>> for my ($foo, $bar, $baz) (@array) {
>> # $foo, $bar, and $baz are the next three elements of @array,
>> # or undef if overflowed
>>
>> # Rationale
>>
>> The existing syntax to iterate over the keys and values of a hash:
>>
>> while (my ($key, $value) = each %hash) { ... }
>>
>> suffers from several problems
>>
>> * For correctness it assumes that the internal state of the hash being
>> "clean" - to be robust one should reset the iterator first with `keys
>> %hash;` in void context
>> * It's hard to teach to beginners - to understand what is going on here
>> one needs to know
>> - list assignment
>> - empty lists are false; non-empty lists are true
>> - that the hash holds an internal iterator
>> * You can't modify the hash inside the loop without confusing the iterator
>>
>> The proposed syntax solves all of these.
>>
>> # Specification
>>
>> # Backwards Compatibility
>>
>> # Security Implications
>>
>> # Examples
>>
>> *FIXME* - are there useful examples that aren't in the Motivation/
>>
>> # Prototype Implementation
>>
>> "Here's one I made earlier" applies - we already have one written, so
>> there's no need to duplicate work
>>
>> # Rejected Ideas
>>
>> # Open Issues
>>
>>
>> # Copyright
>>
>> Copyright (C) 2021, Nicholas Clark
>>
>> This document and code and documentation within it may be used,
>> redistributed and/or modified under the same terms as Perl itself.
>>
>
Re: RFC: Multiple-alias syntax for for [ In reply to ]
Cicero: The sinews of Perl are an infinite supply of CPAN.

CPAN contains many variants on this theme as shown in the example below.
Please tell me how this proposal would improve upon them well enough to
justify the immense effort of implementing this new feature in the core of
Perl?

use Test::More qw(no_plan);
use feature qw(say state current_sub);

sub forEachKeyValue(&%)
# Iterate over a hash for each key and value
{my ($body, %hash) = @_;
# Body to be executed, hash to be iterated
&$body($_, $hash{$_}) for sort keys %hash;
}

my %h = (a=>1, b=>2, c=>3);
my @t;

forEachKeyValue
{my ($letter, $number) = @_;
push @t, "Letter=$letter, number=$number";
} %h;

is_deeply join("\n", @t, ''), <<END;
Letter=a, number=1
Letter=b, number=2
Letter=c, number=3
END


On Tue, Jun 8, 2021 at 6:02 PM Scott Baker <scott@perturb.org> wrote:

> This is a great example.
>
> I support this syntax 100%. Well done.
>
> On 6/8/2021 4:20 AM, Nicholas Clark wrote:
> > So, the plan for discussing the proposed RFC process was to feed an idea
> > through it, and see how we get from idea to RFC to implementation.
> > (Assuming that we don't reject the idea.)
> >
> > About two months ago Rik had mentioned to me the idea of implementing
> this
> > (currently illegal) syntax to iterate over hashes:
> >
> > for my ($key, $value) (%hash) { ... }
> >
> > which isn't actually hash specific - it generalises to N-at-a-time over
> any
> > list.
> >
> > I figured that the *runtime* part probably wasn't that hard, so had a
> crack
> > implementing that, assuming that I'd get help with the parser part once I
> > had an idea how the runtime and the optree needed to be. Except that I
> > didn't get stuck, and got to a complete implementation, which has been
> > pushed somewhere public for 6 weeks now.
> >
> > ( somewhere reachable in 6 clicks from https://github.com/Perl/RFCs )
> >
> > So, if you have the time and skills, please try implementing something
> else
> > that would improve Perl, as re-implementing this is duplication of
> effort.
> >
> >
> >
> > By chance, I started on this a couple of days before KES777 submitted
> > https://github.com/Perl/perl5/issues/18744
> > and in turn, that links to a message from Dan Brook in 2017 proposing it:
> >
> https://www.nntp.perl.org/group/perl.perl5.porters/2017/03/msg243848.html
> >
> >
> > So, rather than start on the RFC by "faking" an "idea" mail from Rik,
> I'll
> > take the genuine item from Dan:
> >
> > On Fri, Mar 31, 2017 at 06:39:59PM -0400, Dan Book wrote:
> >> The "each" function is generally discouraged due to implementation
> details,
> >> but is still the most "pretty" and concise way to write such a loop:
> >>
> >> while (my ($key, $value) = each %hash) { ... }
> >>
> >> A possible alternative to this would be a syntax to alias multiple items
> >> per iteration in a for/foreach loop.
> >>
> >> foreach my ($key, $value) (%hash) { ... }
> >>
> >> This could be generalized as a "bundler", in other words to alias a
> number
> >> of elements from the list equal to the number of variables specified.
> Such
> >> as:
> >>
> >> foreach my ($foo, $bar, $baz) (@array) { # $foo, $bar, and $baz are the
> >> next three elements of @array, or undef if overflowed
> >>
> >> I can think of one syntactical issue presently: "foreach ($foo, $bar)"
> >> without the "my" is already valid syntax so would be difficult to
> >> disambiguate without looking for the second () denoting the list to
> iterate
> >> through.
> >>
> >> Thoughts?
> >>
> >> -Dan
> >
> > This arrives here:
> >
> > idea
> > |
> > v
> > mail p5p
> > |
> > better | rejected
> > on <-------?-------> with
> > CPAN | reasoning
> > v
> > Draft RFC
> > "we think this idea is worth exploring"
> > (Help us figure out how this will work)
> >
> >
> > For this idea, "we think this idea is worth exploring" applies, so we
> need
> > a draft.
> >
> >
> > So
> >
> > 1) I need to assign an ID.
> >
> > Question - do I start at 0001, or keep low numbers for "something
> special"?
> > I'm guessing "start at 0001"
> >
> >
> > 2) Format - PSC had thought Markdown, as many places can render it.
> >
> > However,
> >
> > a) github itself can render Pod. Is it the only git hosting service that
> can?
> > b) I've already found that my local markdown renderer and github disagree
> > about nested lists, which is annoying - how many other bugs will I
> hit?
> > c) Pod doesn't do tables, but plain markdown doesn't either.
> > github extended markdown with tables, but
> > i) How many other markdown implementations follow them?
> > ii) Are there alternative competing "table" dialects of Markdown?
> > d) I'm missing =cut
> >
> >
> > 3) Who is the formal "Author" of this RFC. Does Dan want to be named?
> > Currently I seem to be ghost writing it, but if I become the author,
> > then someone else needs to take over as sponsor?
> > Should the copyright be Dan, and 2017?
> >
> >
> > Appended is my first draft, as if I'd only read Dan's mail.
> >
> > I figure that as there has already been some discussion on github in 2021
> > and p5p in 2017, I should act as if that came in reply to this message,
> > and try taking this from here, by filling in some of the other sections.
> >
> > Nicholas Clark
> >
> >
> >
> > # Preamble
> >
> > Author:
> > Sponsor: Nicholas Clark <nick@ccl4.org>
> > ID: 0001
> > Status: Draft
> > Title: Multiple-alias syntax for foreach
> >
> > # Abstract
> >
> > Implement the currently illegal syntax `for my ($key, $value) (%hash) {
> ... }` to act as two-at-a-time iteration over hashes. This approach is not
> specific to hashes - it generalises to n-at-a-time over any list.
> >
> > # Motivation
> >
> > The `each` function is generally discouraged due to implementation
> details, but is still the most "pretty" and concise way to write such a
> loop:
> >
> > while (my ($key, $value) = each %hash) { ... }
> >
> > An alternative to this would be a syntax to alias multiple items per
> iteration in a `for` loop.
> >
> > for my ($key, $value) (%hash) { ... }
> >
> > This generalizes as a "bundler" - to alias a number of elements from the
> list equal to the number of variables specified. Such as:
> >
> > for my ($foo, $bar, $baz) (@array) {
> > # $foo, $bar, and $baz are the next three elements of @array,
> > # or undef if overflowed
> >
> > # Rationale
> >
> > The existing syntax to iterate over the keys and values of a hash:
> >
> > while (my ($key, $value) = each %hash) { ... }
> >
> > suffers from several problems
> >
> > * For correctness it assumes that the internal state of the hash being
> "clean" - to be robust one should reset the iterator first with `keys
> %hash;` in void context
> > * It's hard to teach to beginners - to understand what is going on here
> one needs to know
> > - list assignment
> > - empty lists are false; non-empty lists are true
> > - that the hash holds an internal iterator
> > * You can't modify the hash inside the loop without confusing the
> iterator
> >
> > The proposed syntax solves all of these.
> >
> > # Specification
> >
> > # Backwards Compatibility
> >
> > # Security Implications
> >
> > # Examples
> >
> > *FIXME* - are there useful examples that aren't in the Motivation/
> >
> > # Prototype Implementation
> >
> > "Here's one I made earlier" applies - we already have one written, so
> there's no need to duplicate work
> >
> > # Rejected Ideas
> >
> > # Open Issues
> >
> >
> > # Copyright
> >
> > Copyright (C) 2021, Nicholas Clark
> >
> > This document and code and documentation within it may be used,
> redistributed and/or modified under the same terms as Perl itself.
> >
>
Re: RFC: Multiple-alias syntax for for [ In reply to ]
For this specific example you can't really make one that does both the hash
iteration and multiple values from a list iteration. That said you can do
it with keywords currently from a module, see my old example that
implements essentially the entire listed behavior with Keyword::Simple

#!/usr/bin/env perl

use v5.20;

use Keyword::Simple;
use PPR;
use Data::Dumper;
use List::UtilsBy qw/bundle_by/;
use Carp;

BEGIN {
Keyword::Simple::define 'foreach', sub {
my ($ref) = @_;

# TODO make this better

my $scalar_list = qr/
\((?&PerlVariableScalar)(\s*,\s*(?&PerlVariableScalar))*\)
|
(?&PerlVariableScalar)
$PPR::GRAMMAR
/x;

my $regex = qr/\s*
(?<decl>my\s*)?(?<scalar_list>$scalar_list)
\s*
(?<input_value>(?&PerlParenthesesList))
\s*
(?<block>(?&PerlBlock))
/x;

if ($$ref =~ $regex) {

my ($input_value, $scalar_list, $block, $decl) = @+{qw/input_value
scalar_list block decl/};
# do sub here
my $scalar_count = ($scalar_list =~ y/,//)+1;

#TODO pick a non-conspicuous name for this
my $newcode = qq{
for my \$bundle (bundle_by {[\@_]} $scalar_count, $input_value)
{
$decl ($scalar_list) = \@\$bundle;

$block
}
};
my $oldcode = $$ref."";
substr $$ref, $-[0], $+[0]-$-[0], $newcode; # delete it so i see
all parsing
#warn "PARSED SUCCESS ".Data::Dumper->Dump( [\%+, $$ref, $oldcode],
[qw/captured changed orig/]);

} else {
carp "SYNTAX ERROR";
}


};
}

package main;

my %hash = (foo => 1, bar => 2);
my @array = (1,2,3, -1,-2,-3);

foreach my ($k, $v) (%hash) {
say "$k => $v";
}

foreach my ($x, $y, $z) (@array) {
say "($x, $y, $z)";
}

On Tue, Jun 8, 2021 at 2:09 PM Philip R Brenan <philiprbrenan@gmail.com>
wrote:

> Cicero: The sinews of Perl are an infinite supply of CPAN.
>
> CPAN contains many variants on this theme as shown in the example below.
> Please tell me how this proposal would improve upon them well enough to
> justify the immense effort of implementing this new feature in the core of
> Perl?
>
> use Test::More qw(no_plan);
> use feature qw(say state current_sub);
>
> sub forEachKeyValue(&%)
> # Iterate over a hash for each key and value
> {my ($body, %hash) = @_;
> # Body to be executed, hash to be iterated
> &$body($_, $hash{$_}) for sort keys %hash;
> }
>
> my %h = (a=>1, b=>2, c=>3);
> my @t;
>
> forEachKeyValue
> {my ($letter, $number) = @_;
> push @t, "Letter=$letter, number=$number";
> } %h;
>
> is_deeply join("\n", @t, ''), <<END;
> Letter=a, number=1
> Letter=b, number=2
> Letter=c, number=3
> END
>
>
> On Tue, Jun 8, 2021 at 6:02 PM Scott Baker <scott@perturb.org> wrote:
>
>> This is a great example.
>>
>> I support this syntax 100%. Well done.
>>
>> On 6/8/2021 4:20 AM, Nicholas Clark wrote:
>> > So, the plan for discussing the proposed RFC process was to feed an idea
>> > through it, and see how we get from idea to RFC to implementation.
>> > (Assuming that we don't reject the idea.)
>> >
>> > About two months ago Rik had mentioned to me the idea of implementing
>> this
>> > (currently illegal) syntax to iterate over hashes:
>> >
>> > for my ($key, $value) (%hash) { ... }
>> >
>> > which isn't actually hash specific - it generalises to N-at-a-time over
>> any
>> > list.
>> >
>> > I figured that the *runtime* part probably wasn't that hard, so had a
>> crack
>> > implementing that, assuming that I'd get help with the parser part once
>> I
>> > had an idea how the runtime and the optree needed to be. Except that I
>> > didn't get stuck, and got to a complete implementation, which has been
>> > pushed somewhere public for 6 weeks now.
>> >
>> > ( somewhere reachable in 6 clicks from https://github.com/Perl/RFCs )
>> >
>> > So, if you have the time and skills, please try implementing something
>> else
>> > that would improve Perl, as re-implementing this is duplication of
>> effort.
>> >
>> >
>> >
>> > By chance, I started on this a couple of days before KES777 submitted
>> > https://github.com/Perl/perl5/issues/18744
>> > and in turn, that links to a message from Dan Brook in 2017 proposing
>> it:
>> >
>> https://www.nntp.perl.org/group/perl.perl5.porters/2017/03/msg243848.html
>> >
>> >
>> > So, rather than start on the RFC by "faking" an "idea" mail from Rik,
>> I'll
>> > take the genuine item from Dan:
>> >
>> > On Fri, Mar 31, 2017 at 06:39:59PM -0400, Dan Book wrote:
>> >> The "each" function is generally discouraged due to implementation
>> details,
>> >> but is still the most "pretty" and concise way to write such a loop:
>> >>
>> >> while (my ($key, $value) = each %hash) { ... }
>> >>
>> >> A possible alternative to this would be a syntax to alias multiple
>> items
>> >> per iteration in a for/foreach loop.
>> >>
>> >> foreach my ($key, $value) (%hash) { ... }
>> >>
>> >> This could be generalized as a "bundler", in other words to alias a
>> number
>> >> of elements from the list equal to the number of variables specified.
>> Such
>> >> as:
>> >>
>> >> foreach my ($foo, $bar, $baz) (@array) { # $foo, $bar, and $baz are the
>> >> next three elements of @array, or undef if overflowed
>> >>
>> >> I can think of one syntactical issue presently: "foreach ($foo, $bar)"
>> >> without the "my" is already valid syntax so would be difficult to
>> >> disambiguate without looking for the second () denoting the list to
>> iterate
>> >> through.
>> >>
>> >> Thoughts?
>> >>
>> >> -Dan
>> >
>> > This arrives here:
>> >
>> > idea
>> > |
>> > v
>> > mail p5p
>> > |
>> > better | rejected
>> > on <-------?-------> with
>> > CPAN | reasoning
>> > v
>> > Draft RFC
>> > "we think this idea is worth exploring"
>> > (Help us figure out how this will work)
>> >
>> >
>> > For this idea, "we think this idea is worth exploring" applies, so we
>> need
>> > a draft.
>> >
>> >
>> > So
>> >
>> > 1) I need to assign an ID.
>> >
>> > Question - do I start at 0001, or keep low numbers for "something
>> special"?
>> > I'm guessing "start at 0001"
>> >
>> >
>> > 2) Format - PSC had thought Markdown, as many places can render it.
>> >
>> > However,
>> >
>> > a) github itself can render Pod. Is it the only git hosting service
>> that can?
>> > b) I've already found that my local markdown renderer and github
>> disagree
>> > about nested lists, which is annoying - how many other bugs will I
>> hit?
>> > c) Pod doesn't do tables, but plain markdown doesn't either.
>> > github extended markdown with tables, but
>> > i) How many other markdown implementations follow them?
>> > ii) Are there alternative competing "table" dialects of Markdown?
>> > d) I'm missing =cut
>> >
>> >
>> > 3) Who is the formal "Author" of this RFC. Does Dan want to be named?
>> > Currently I seem to be ghost writing it, but if I become the author,
>> > then someone else needs to take over as sponsor?
>> > Should the copyright be Dan, and 2017?
>> >
>> >
>> > Appended is my first draft, as if I'd only read Dan's mail.
>> >
>> > I figure that as there has already been some discussion on github in
>> 2021
>> > and p5p in 2017, I should act as if that came in reply to this message,
>> > and try taking this from here, by filling in some of the other sections.
>> >
>> > Nicholas Clark
>> >
>> >
>> >
>> > # Preamble
>> >
>> > Author:
>> > Sponsor: Nicholas Clark <nick@ccl4.org>
>> > ID: 0001
>> > Status: Draft
>> > Title: Multiple-alias syntax for foreach
>> >
>> > # Abstract
>> >
>> > Implement the currently illegal syntax `for my ($key, $value) (%hash) {
>> ... }` to act as two-at-a-time iteration over hashes. This approach is not
>> specific to hashes - it generalises to n-at-a-time over any list.
>> >
>> > # Motivation
>> >
>> > The `each` function is generally discouraged due to implementation
>> details, but is still the most "pretty" and concise way to write such a
>> loop:
>> >
>> > while (my ($key, $value) = each %hash) { ... }
>> >
>> > An alternative to this would be a syntax to alias multiple items per
>> iteration in a `for` loop.
>> >
>> > for my ($key, $value) (%hash) { ... }
>> >
>> > This generalizes as a "bundler" - to alias a number of elements from
>> the list equal to the number of variables specified. Such as:
>> >
>> > for my ($foo, $bar, $baz) (@array) {
>> > # $foo, $bar, and $baz are the next three elements of @array,
>> > # or undef if overflowed
>> >
>> > # Rationale
>> >
>> > The existing syntax to iterate over the keys and values of a hash:
>> >
>> > while (my ($key, $value) = each %hash) { ... }
>> >
>> > suffers from several problems
>> >
>> > * For correctness it assumes that the internal state of the hash being
>> "clean" - to be robust one should reset the iterator first with `keys
>> %hash;` in void context
>> > * It's hard to teach to beginners - to understand what is going on here
>> one needs to know
>> > - list assignment
>> > - empty lists are false; non-empty lists are true
>> > - that the hash holds an internal iterator
>> > * You can't modify the hash inside the loop without confusing the
>> iterator
>> >
>> > The proposed syntax solves all of these.
>> >
>> > # Specification
>> >
>> > # Backwards Compatibility
>> >
>> > # Security Implications
>> >
>> > # Examples
>> >
>> > *FIXME* - are there useful examples that aren't in the Motivation/
>> >
>> > # Prototype Implementation
>> >
>> > "Here's one I made earlier" applies - we already have one written, so
>> there's no need to duplicate work
>> >
>> > # Rejected Ideas
>> >
>> > # Open Issues
>> >
>> >
>> > # Copyright
>> >
>> > Copyright (C) 2021, Nicholas Clark
>> >
>> > This document and code and documentation within it may be used,
>> redistributed and/or modified under the same terms as Perl itself.
>> >
>>
>
Re: RFC: Multiple-alias syntax for for [ In reply to ]
Ryan,
> Sorry about that, I recovered the wrong old paste, this is the right one: https://perl.bot/p/8ax2rw
> > [N lines of text]

When replying on p5p, please be considerate of the ~500 subscribers to p5p and trim the parts of the message that you’re not directly replying to.

When you include all of a long message like that, I scan through it all, in case you’ve replied to some part of it inline, and I’m sure others will as well.

Neil
Re: RFC: Multiple-alias syntax for for [ In reply to ]
Perl already has this feature.


@triples % 3 and die "TRIPLES ARRAY NOT MULTIPLE OF 3 IN LENGTH";
while (@triples){
my ($foo, $bar, $baz) = splice @triples, 0, 3;
...
}




--
"Lay off that whiskey, and let that cocaine be!" -- Johnny Cash
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, 8 Jun 2021 14:23:26 -0500
David Nicol <davidnicol@gmail.com> wrote:

> Perl already has this feature.
>
>
> @triples % 3 and die "TRIPLES ARRAY NOT MULTIPLE OF 3 IN LENGTH";
> while (@triples){
> my ($foo, $bar, $baz) = splice @triples, 0, 3;
> ...
> }

We do, but it's not very nice for two reasons:

1) DRY failure - you've written `@triples` once in the looping
condition and then a second time in the `splice`

2) It's destructive on the array

Combined, that means it's impossible to run it on any non-variable
expression, such as the result of a function call. Whereas, calling a
function is just as possible with the multivariabled foreach:

foreach my ($red, $green, $blue) (get_palette()) {
...
}

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, Jun 8, 2021 at 3:35 PM Paul "LeoNerd" Evans <leonerd@leonerd.org.uk>
wrote:

> On Tue, 8 Jun 2021 14:23:26 -0500
> David Nicol <davidnicol@gmail.com> wrote:
>
> > Perl already has this feature.
> >
> >
> > @triples % 3 and die "TRIPLES ARRAY NOT MULTIPLE OF 3 IN LENGTH";
> > while (@triples){
> > my ($foo, $bar, $baz) = splice @triples, 0, 3;
> > ...
> > }
>
> We do, but it's not very nice for two reasons:
>
> 1) DRY failure - you've written `@triples` once in the looping
> condition and then a second time in the `splice`
>
> 2) It's destructive on the array
>
> Combined, that means it's impossible to run it on any non-variable
> expression, such as the result of a function call. Whereas, calling a
> function is just as possible with the multivariabled foreach:
>
> foreach my ($red, $green, $blue) (get_palette()) {
> ...
> }
>

Also it doesn't work on hashes.

-Dan
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, 8 Jun 2021 at 13:21, Nicholas Clark <nick@ccl4.org> wrote:

> So, the plan for discussing the proposed RFC process was to feed an idea
> through it, and see how we get from idea to RFC to implementation.
> (Assuming that we don't reject the idea.)
>
> About two months ago Rik had mentioned to me the idea of implementing this
> (currently illegal) syntax to iterate over hashes:
>
> for my ($key, $value) (%hash) { ... }
>
>
Alternative proposal (as part of more complex proposal I'm preparing, based
on https://gist.github.com/happy-barney/d94d3a6d30b4529ab86ef5ea6c78a043)
Just as code samples

# iterate by two elements, die odd number of numbers
for (@list) {
has ($key, $value);
}

# iterate by three elements, use default values if @list % 3 != 0
for (@list) {
has $first;
has $second := :default => 'foo';
has $third := :default => 'bar';
}

# iterate over keys only
for (%hash) {
has $key := :is => HASH::key;
}

# iterate over list with index
for (@list) {
has $index := :is => ARRAY::index;
has $value;
}
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, Jun 08, 2021 at 03:50:07PM -0400, Dan Book wrote:
> On Tue, Jun 8, 2021 at 3:35 PM Paul "LeoNerd" Evans <leonerd@leonerd.org.uk>
> wrote:
>
> > On Tue, 8 Jun 2021 14:23:26 -0500
> > David Nicol <davidnicol@gmail.com> wrote:
> >
> > > Perl already has this feature.

Your statement "has this feature" is not accurate. What you show below
is using existing functionality (features, *plural*) to implement the
behaviour.

What you mean is "Perl does not need a special feature for this because it
can be implemented with existing features".

Which in itself is a sensible argument against adding a feature.

Trouble is, that Perl is a Turing complete language. Meaning that *any*
possible new feature that could be proposed can already be implemented with
existing functionality.

So arguing against a new feature because it is already possible is, well,
tautological.


So, I assume that what you are really trying to argue is:

Perl does not need a special feature for this because it can be *easily*
be implemented with existing features.


Which gets us to:

> > > @triples % 3 and die "TRIPLES ARRAY NOT MULTIPLE OF 3 IN LENGTH";
> > > while (@triples){
> > > my ($foo, $bar, $baz) = splice @triples, 0, 3;
> > > ...
> > > }
> >
> > We do, but it's not very nice for two reasons:
> >
> > 1) DRY failure - you've written `@triples` once in the looping
> > condition and then a second time in the `splice`
> >
> > 2) It's destructive on the array
> >
> > Combined, that means it's impossible to run it on any non-variable
> > expression, such as the result of a function call. Whereas, calling a
> > function is just as possible with the multivariabled foreach:
> >
> > foreach my ($red, $green, $blue) (get_palette()) {
> > ...
> > }
> >
>
> Also it doesn't work on hashes.

Or efficiently on things like ranges. The syntax (1..9999999) doesn't
actually generate a temporary list of 9,999,999 items:

$ ./perl -Ilib -MO=Concise,-exec -e 'for my $c (1..9999999) { ... } '
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <0> pushmark s
4 <$> const(IV 1) s
5 <$> const(IV 9999999) s
6 <{> enteriter(next->b last->e redo->7)[$c:2,5] vKS/LVINTRO
c <0> iter s
d <|> and(other->7) vK/1
7 <;> nextstate(main 4 -e:1) v
8 <0> pushmark s
9 <$> const(PV "Unimplemented") s
a <@> die vK/1
b <0> unstack v
goto c
e <2> leaveloop vK/2
f <@> leave[1 ref] vKP/REFC
-e syntax OK


The approach your suggesting would require creating a temporary array to
hold the contents of the list (or hash, or array you don't want to destroy)
- this is a bunch of copying that the direct syntax avoids.

I *think* that one could use a loop like this to avoid the destructive splice:

for (my $i = 0; $i < @array; $i += 3) {
my ($foo, $bar, $baz) = @array[$i .. $i + 2];
...
}

but I've deliberately *not* tested that, as my point is that there are
several things that I know that I might get wrong here (boundary cases in
the for loop, boundary cases in the list slice) - it's "no obvious bugs"

Whereas the proposed syntax is

for my ($foo, $bar, $baz) (@array) {
...
}

"obviously no bugs" (famous last words)


Finally, foreach *aliases* its iterator - if the loop actually wants to
modify the values in-place, any "copying" approach isn't going to solve the
programmer's problem easily.


This gets back to the non-tautological argument:

Perl does not need a special feature for this because it can be *easily*
be implemented with existing features.


I don't think that this is true.

The existing approaches are more verbose, and have many ways to make
mistakes.

Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, Jun 08, 2021 at 07:09:20PM +0100, Philip R Brenan wrote:
> Cicero: The sinews of Perl are an infinite supply of CPAN.
>
> CPAN contains many variants on this theme as shown in the example below.
> Please tell me how this proposal would improve upon them well enough to
> justify the immense effort of implementing this new feature in the core of
> Perl?

"immense effort"

Down in the part that everyone quoted, but didn't seem to read:

> > > # Prototype Implementation
> > >
> > > "Here's one I made earlier" applies - we already have one written, so
> > there's no need to duplicate work

I believe that it took me about 3 days to implement this.

By the standards of what it would take to implement some of the language
changes I've seen proposed, that is trivial.

Moreover, it's relatively self contained, so relatively low risk.

Runtime changes are in one function in one file:

$ git diff -w --stat fd11779cdb4d6f04f5f869d890845a060b696bba pp_hot.c
1 file changed, 80 insertions(+), 19 deletions(-)

optree generation changes are small:

$ git diff -w --stat fd11779cdb4d6f04f5f869d890845a060b696bba op.c
1 file changed, 62 insertions(+), 4 deletions(-)

Grammar changes are small:

$ git diff --stat fd11779cdb4d6f04f5f869d890845a060b696bba perly.y
1 file changed, 20 insertions(+), 1 deletion(-)


One doesn't *need* sufficient knowledge to implement changes to be able to
discuss whether the trade offs are worth it, but one does need a good
*feel* for what is hard/what is not, before passing judgement on the
risk/reward of an idea. I didn't set off knowing that it would be exactly
this small, but I had an idea that likely it would be, because I knew
what shape the runtime code for `for` has (and it's not very large.)



As to your suggestion:

> sub forEachKeyValue(&%)
> # Iterate over a hash for each key and value
> {my ($body, %hash) = @_;
> # Body to be executed, hash to be iterated
> &$body($_, $hash{$_}) for sort keys %hash;
> }
>
> my %h = (a=>1, b=>2, c=>3);
> my @t;
>
> forEachKeyValue
> {my ($letter, $number) = @_;
> push @t, "Letter=$letter, number=$number";
> } %h;


Right now, if I need to iterate over key and value combined, I'm tempted
to write:

for my $k (keys %hash) {
my $v = $hash{$h};
...
}


That's a lot fewer lines than your suggestion, and doesn't *copy* the entire
hash, avoids a lot of function calls, and I can choose whether I want to
sort or not.

Yes, it works.

But it doesn't generalise to n-at-a-time iteration over arbitrary lists (or
arrays), which the proposed syntax does.

Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, Jun 08, 2021 at 09:55:23PM +0200, Branislav Zahradn?k wrote:
> On Tue, 8 Jun 2021 at 13:21, Nicholas Clark <nick@ccl4.org> wrote:
>
> > So, the plan for discussing the proposed RFC process was to feed an idea
> > through it, and see how we get from idea to RFC to implementation.
> > (Assuming that we don't reject the idea.)
> >
> > About two months ago Rik had mentioned to me the idea of implementing this
> > (currently illegal) syntax to iterate over hashes:
> >
> > for my ($key, $value) (%hash) { ... }
> >
> >
> Alternative proposal (as part of more complex proposal I'm preparing, based
> on https://gist.github.com/happy-barney/d94d3a6d30b4529ab86ef5ea6c78a043)
> Just as code samples
>
> # iterate by two elements, die odd number of numbers
> for (@list) {
> has ($key, $value);
> }
>
> # iterate by three elements, use default values if @list % 3 != 0
> for (@list) {
> has $first;
> has $second := :default => 'foo';
> has $third := :default => 'bar';
> }
>
> # iterate over keys only
> for (%hash) {
> has $key := :is => HASH::key;
> }

I'm not sure what that wins over the existing

for my $key (keys %hash) {
}

and using your `has` approach the key/value pairing could be written as

# iterate by two elements, die odd number of numbers
for (%hash) {
has ($key, $value);
}

relying on existing list flattening.

I appreciate that this is syntax that is intended to be massively more
flexible, but it's conjectured on several things that aren't yet designed,
let alone implemented

* `has` for class attributes
* extending `has` more generally (here, for blocks)
* variable binding syntax `:=`
* some level of auto-boxing on HASHes, or a HASH namespace that behaves in
"interesting" ways with the parser.

I think that this could make sense once Cor is in the core, but unlike the
proposal, it's not something that we could have land next week - it's part
of a much bigger (coherent) design, that isn't firm yet.


Also, this is Perl - "There's More Than One Way To Do It" is acceptable.
("But I hesitate to make ten" also applies).

The two syntaxes for the same thing can coexist in the future - one is
"easy things easy", the other enables "hard things possible".


We don't need to get into a tailspin about "which is more Pythonic".
We can have both. Having one doesn't rule out the other.

(This seems to be what happens on Stack Overflow etc as soon as it becomes
apparent that there are multiple reasonable solutions to a problem, and
hence it is axiomatic that is necessary to figure out which is unequivocally
best.)

Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, 8 Jun 2021 11:20:57 +0000
Nicholas Clark <nick@ccl4.org> wrote:

> About two months ago Rik had mentioned to me the idea of implementing this
> (currently illegal) syntax to iterate over hashes:
>
> for my ($key, $value) (%hash) { ... }
>
> which isn't actually hash specific - it generalises to N-at-a-time over any
> list.

I love this feature, it's something I've been really missing in Perl.
Also, I'm really glad we finally have an RFC process :)

> 2) Format - PSC had thought Markdown, as many places can render it.
>
> However,
>
> a) github itself can render Pod. Is it the only git hosting service that can?
> b) I've already found that my local markdown renderer and github disagree
> about nested lists, which is annoying - how many other bugs will I hit?
> c) Pod doesn't do tables, but plain markdown doesn't either.
> github extended markdown with tables, but
> i) How many other markdown implementations follow them?
> ii) Are there alternative competing "table" dialects of Markdown?
> d) I'm missing =cut

Personally, I'm in favor of POD, dogfooding FTW. I don't know about the
other git hosting services, but why does it matter? We are using Github.
Re: RFC: Multiple-alias syntax for for [ In reply to ]
Den 08.06.2021 13:20, skrev Nicholas Clark:
> So, the plan for discussing the proposed RFC process was to feed an idea
> through it, and see how we get from idea to RFC to implementation.
> (Assuming that we don't reject the idea.)
>
> About two months ago Rik had mentioned to me the idea of implementing this
> (currently illegal) syntax to iterate over hashes:
>
> for my ($key, $value) (%hash) { ... }

I'm sorry if this is the wrong place to comment, but I see several
comments about the proposition itself, so here goes:

I really like this, it makes life simpler.

I was wondering though:

1) since it looks like such an obvious improvement but hasn't been done
before, is there some reason that one hasn't gone down this route
before? Are there some hidden gotchas about it? Or is it just genius
overlooked simplification?

2) will this work flawlessly with for instance: for my ($key $value,
%rest) = (%hash) { … } (iterating only once)

3) will it work transparently with foreach (I believe I saw some
comments about that)

If there is a more suitable place to ask these questions or comment,
please enlighten me.

--

Nicolas Mendoza
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Wed, Jun 9, 2021 at 7:44 PM Nicolas Mendoza <mendoza@pvv.ntnu.no> wrote:

>
> 1) since it looks like such an obvious improvement but hasn't been done
> before, is there some reason that one hasn't gone down this route
> before? Are there some hidden gotchas about it? Or is it just genius
> overlooked simplification?
>

I suspect no proposal has gotten far enough in implementation yet to be
usefully discussed.


> 2) will this work flawlessly with for instance: for my ($key $value,
> %rest) = (%hash) { … } (iterating only once)
>

I don't see why this should be supported and complicate the implementation,
since you can just do that assignment without any loop.


> 3) will it work transparently with foreach (I believe I saw some
> comments about that)
>

Not sure what you mean; this is a feature specifically for foreach.

-Dan
Re: RFC: Multiple-alias syntax for for [ In reply to ]
Den 10.06.2021 03:37, skrev Dan Book:
>
> 2) will this work flawlessly with for instance: for my ($key $value,
> %rest) = (%hash) { … } (iterating only once)
>
>
> I don't see why this should be supported and complicate
> the implementation, since you can just do that assignment without any
> loop.

I see I wrote the wrong syntax, I meant that since it is supposed to
work n-at-a-time, what would it do when having a hash or an array on the
left side. Would it behave similar to constructs not in a for-loop like
classical argument assignment (my ($self, $in, %opt) = @_; or just die?

for my ($key, $value, %rest) (%hash) { … } # one iteration or syntax error?

for my ($first, $second, @rest) (@array) { … } # one iteration or syntax
error?

for my ($a, $b, $c) (@array) { … } # int($#array / 3) + ($#array % 3)
iterations?

for my (@a) (@array) { … } # one iteration or syntax error

for my ($a, $b, undef) ((1,2,3)) { … } # one iteration or syntax error--

--

Nicolas Mendoza
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, Jun 10, 2021 at 01:43:43AM +0200, Nicolas Mendoza wrote:
>
> Den 08.06.2021 13:20, skrev Nicholas Clark:
> > So, the plan for discussing the proposed RFC process was to feed an idea
> > through it, and see how we get from idea to RFC to implementation.
> > (Assuming that we don't reject the idea.)
> >
> > About two months ago Rik had mentioned to me the idea of implementing this
> > (currently illegal) syntax to iterate over hashes:
> >
> > for my ($key, $value) (%hash) { ... }
>
> I'm sorry if this is the wrong place to comment, but I see several comments
> about the proposition itself, so here goes:

No, this is totally the right place to comment.

It's sensible comments like this (particularly comments from people whose
names I don't recognise) that we'd like to see.

> I really like this, it makes life simpler.

That was what I thought when I first saw the idea. But I'm not sure if I'm
biased. :-)

On Wed, Jun 09, 2021 at 09:37:42PM -0400, Dan Book wrote:
> On Wed, Jun 9, 2021 at 7:44 PM Nicolas Mendoza <mendoza@pvv.ntnu.no> wrote:
>
> >
> > 1) since it looks like such an obvious improvement but hasn't been done
> > before, is there some reason that one hasn't gone down this route
> > before? Are there some hidden gotchas about it? Or is it just genius
> > overlooked simplification?
> >
>
> I suspect no proposal has gotten far enough in implementation yet to be
> usefully discussed.

I really don't know.

I'm going to guess that it's a few things

1) historically to get something implemented required some luck - it needed
an idea to arrive with someone who stood a chance of implementing it
(this is still true, I guess)
And most of those people already have a bunch more ideas that they'd like
to try than time to do it. So
i) either *they* have to have this great idea and start work on it
ii) someone else has to have an idea *so* great that it's better than any
of their ideas, and they drop their other free-time plans

2) I re-read the previous discussions - as ever, some people said
"I don't think that this is useful enough" whereas others said
"that seems cool", but there wasn't an "executive" decision made to
conclude the discussion. So it hangs as "maybe".
In particular there isn't an affirmative "if you did put the effort into
trying to implement this, it will be accepted". A policy decision isn't
made - any work you do is at risk of being ignore

3) When Rik mentioned the basic idea to me about two months ago, he knew that
the syntax was "low risk" - it fits in nicely and is currently an error.
I was far more enthusiastic than he expected because I had some idea that
the runtime was *also* "low risk" - get the internal data structures right
and code changes would only be needed in one OP. So it looked "easy", and
seemed like a good surprise to launch a future (likely) 5.36.0 with,
given that we expected 5.34.0 to be a bit low key.

which is how we ended up with me hacking up implementation over a weekend
and a bit, about 6 weeks ago. And then we had to sit on it...


During which time I figured out that (1) I really wanted an RFC process
(2) Heck, there were still some unanswered questions in what I did, and
given that we'd have to answer them anyway, why not *use* this idea to
test the RFC process, and see if it can answer the questions.

You've actually sort of hit on one of the questions (well, one of the
implementation assumptions I made).

> > 3) will it work transparently with foreach (I believe I saw some
> > comments about that)
> >
>
> Not sure what you mean; this is a feature specifically for foreach.

Other folks know (or at least understand) the grammar better than me.
I *think* that `for` and `foreach` are aliases for the same thing. In that,
they are two spellings of the same keyword and once they have been parsed
they are identical.

I admit some guilt and inconsistency here - *I* preferred using `for` in
the code examples because it's 4 characters shorter.

*but* I realised that that makes the title `Multiple-alias syntax for for`
which is daft. So I changed *that* to `foreach`. And now it's inconsistent.
Bad programmer, no cookie.

I don't know what is best.

On Thu, Jun 10, 2021 at 04:00:45AM +0200, Nicolas Mendoza wrote:
>
> Den 10.06.2021 03:37, skrev Dan Book:
> >
> > 2) will this work flawlessly with for instance: for my ($key $value,
> > %rest) = (%hash) { … } (iterating only once)
> >
> >
> > I don't see why this should be supported and complicate
> > the implementation, since you can just do that assignment without any
> > loop.
>
> I see I wrote the wrong syntax, I meant that since it is supposed to work
> n-at-a-time, what would it do when having a hash or an array on the left
> side. Would it behave similar to constructs not in a for-loop like classical
> argument assignment (my ($self, $in, %opt) = @_; or just die?
>
> for my ($key, $value, %rest) (%hash) { … } # one iteration or syntax error?

Syntax error.

> for my ($first, $second, @rest) (@array) { … } # one iteration or syntax
> error?

Syntax error.

> for my ($a, $b, $c) (@array) { … } # int($#array / 3) + ($#array % 3)
> iterations?

This is a question that has to be decided...

What happens here if the list count isn't an integer multiple of 3?

To me, the most obvious answer was substitute undef if it's not
(ie don't die, and don't ignore what would be incomplete 'tuples' at the end)

So if the list has 10 elements, it iterates as

One Two Three
Four Five Six
Seven Eight Nine
Ten undef undef

and with 11, that last iteration is

Ten Eleven undef

> for my (@a) (@array) { … } # one iteration or syntax error

Syntax error. You can only have scalars

> for my ($a, $b, undef) ((1,2,3)) { … } # one iteration or syntax error--

Right. This is the interesting question...

I'm suggesting syntax error.

I think the slightly better question would be express it as

for my ($a, undef, $c) (1 .. 9) { ... }


It's a reasonable generalisation of list assignment, where you can assign to
undef to mean "ignore this value". I can see that this *might* be useful.
It's also safe syntax to implement (although I didn't try, and I'm not sure
how hard it would be).

I'd like to stick to forbidding this, because it makes the implementation
harder.


So, the sort of dirty secret/insight...


The thing I knew before I started was that the code to "get the next
iteration item or terminate the loop" is fairly simple, and really the
only thing that needs changing to go from "1 at a time" to "n at a time".

Also, one might think that Perl internally is a stack machine, but it's
actually sort of hybrid, as many ops can access the Pads directly.
Pads are arrays of (pointers to) SVs - ops store the index of an entry
in the Pad, so arguably this is kind of a register machine.

Rik knew that the syntax only makes sense for a list of lexicals, because
the `my` at that point is a syntax error.

The background is that the perl parser has to know what it is parsing as it
parses it. This syntax:

for ($key, $value) (%hash) { ... }

^
isn't going to work, because at this point the parser things that it has
parsed the list *that is being iterated over* (and done stuff that has
committed itself to this interpretation), meaning that when it sees '('
and not '{' it can't backtrack and change its mind - this is beyond it.

So, that `my (` is all key here - it's currently a syntax error, but making
the `(` legal after `my` lets the grammar know that what is next is a list
of iterator targets.

[.The above part is stuff other people have explained to me.]

The insight I had was that *if* the only thing you allow for "n at time"
iteration is a list of *newly declared lexicals*, then they all sit in
adjacent pad slots.

Right now, this syntax:

for my $key (keys %hash) { ... }

allocates a pad slot for $key, and stores the numeric index of that pad slot
in (actually) the enteriter op. (This was a surprise - the more logical
place would seem to be the iter op):

$ ./perl -Ilib -MO=Concise,-exec -e 'for my $key (keys %hash) { ... }'
1 <0> enter v
2 <;> nextstate(main 1 -e:1) v:{
3 <0> pushmark sM
4 <$> gv(*hash) s
5 <1> rv2hv[t2] lKRM
6 <1> keys[t3] lKM/1
7 <{> enteriter(next->c last->f redo->8)[$key:2,5] vK/LVINTRO
d <0> iter s
e <|> and(other->8) vK/1
8 <;> nextstate(main 4 -e:1) v
9 <0> pushmark s
a <$> const(PV "Unimplemented") s
b <@> die vK/1
c <0> unstack v
goto d
f <2> leaveloop vK/2
g <@> leave[1 ref] vKP/REFC
-e syntax OK


OK, so, if you permit 3-at-a-time iteration, at first glance that seems to
mean that you now need to store 3 pad slots, not 1, and where is there space
to "hide" 2 more integers?

But as long as you are declaring $n lexicals and iterating over $n lexicals,
then you have them in the next slots (ie (1 .. $n - 1)), meaning that you
now only have to find space to store one other integer - it's the "count of
how many we are iterating" - the addresses of the variables to use as
iterators can all be calculated from the known location of the first
variable.

So, it's a lot easier to implement (and a bit faster too, and less likely to
be buggy) if we don't permit undef in the iteration list. And I'd prefer to
keep it that way, at least to start with.


So thanks for asking the right question...

Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, Jun 10, 2021 at 07:28:16AM +0000, Nicholas Clark wrote:
> On Thu, Jun 10, 2021 at 01:43:43AM +0200, Nicolas Mendoza wrote:

> > I'm sorry if this is the wrong place to comment, but I see several comments
> > about the proposition itself, so here goes:
>
> No, this is totally the right place to comment.

And after a coffee, I realise that this is how I think the RFC process
should work. In that

1) this discussion should be summarised in the RFC itself
2) the Author should do this

So as (ghost author) for this RFC, I pushed the appended commit.

Nicholas Clark

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

commit 50e30612a2fc96a2d20b050ab450cc5bfc98c429 (HEAD -> master)
Author: Nicholas Clark <nick@ccl4.org>
Date: Thu Jun 10 09:57:35 2021 +0200

Record why permitting `undef` in the list of scalars is a rejected idea.

Also record explicitly why permitting hashes and arrays isn't worth it.

This explanation prompted by Nicolas Mendoza asking useful questions.

diff --git a/rfcs/rfc0001.md b/rfcs/rfc0001.md
index f2c812f..b93b17e 100644
--- a/rfcs/rfc0001.md
+++ b/rfcs/rfc0001.md
@@ -52,7 +52,7 @@ The proposed syntax solves all of these.

## Examples

-*FIXME* - are there useful examples that aren't in the Motivation/
+*FIXME* - are there useful examples that aren't in the Motivation?

## Prototype Implementation

@@ -60,6 +60,28 @@ The proposed syntax solves all of these.

## Rejected Ideas

+### Permit `undef` in the list of scalars
+
+ for my ($a, undef, $c) (1 .. 9) { ... }
+
+It's a reasonable generalisation of list assignment, where you can assign to undef to mean "ignore this value". I can see that this **might** be useful. It's also safe syntax to implement (although I didn't try, and I'm not sure how hard it would be).
+
+But it adds considerable runtime complexity. The easiest implementation is if there are exactly *n* scalars, all declared in the `for` loop itself, because this way they occupy adjacent Pad slots. This means that there is only one extra integer to store in the optree, which used both to calculate the *n*-at-a-time **and** the addresses of the target variables.
+
+Adding `undef` to the mix rules out a simple, clear implementation.
+
+### Permit @array or %hash in the list of lexicals
+
+ for my ($key, $value, %rest) (%hash) { ... }
+ for my ($first, $second, @rest) (@array) {... }
+
+Syntactically these all "work", and don't violate the assumption that all lexicals are in adjacent Pad slots. But it would add complexity to the runtime. Generalising *1 scalar at a time* to *n at a time* is mostly just adding a C `for` loop around some existing (known working) code.
+
+Implementing these would mean adding code for what is basically a funky way of writing
+
+ { my ($key, $value, %rest) = %hash; ... }
+ { my ($first, $second, @rest) = @array; ... }
+
## Open Issues
Re: RFC: Multiple-alias syntax for for [ In reply to ]
> for my ($key, $value) (%hash) { ... }

Could:

for my ($index, $value) (@array) { ... }

... be in the cards?

I always find it tiring to have to iterate by index using a weird:

for my $i (0..$#array) {
my $value = $array[$i];
# ...

... and I'd rather the golang way (unsure if other languages have it)
of being able to iterate either by value, or key/value for
maps/hashes, or index/value for arrays, specifically.

--
Marco Fontani
+39-329-2180550
perl -E'say v74.65.80.72'
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, Jun 10, 2021 at 3:28 AM Nicholas Clark <nick@ccl4.org> wrote:

>
> I admit some guilt and inconsistency here - *I* preferred using `for` in
> the code examples because it's 4 characters shorter.
>
> *but* I realised that that makes the title `Multiple-alias syntax for for`
> which is daft. So I changed *that* to `foreach`. And now it's inconsistent.
> Bad programmer, no cookie.
>
> I don't know what is best.
>

My preference is to refer to the syntax construct descriptively as
"foreach", since although it is an exact synonym in the grammar, the
C-style for loop is never referred to as a "foreach". Separately from what
any person may decide to write in the actual code.


> > for my ($a, $b, $c) (@array) { … } # int($#array / 3) + ($#array % 3)
> > iterations?
>
> This is a question that has to be decided...
>
> What happens here if the list count isn't an integer multiple of 3?
>
> To me, the most obvious answer was substitute undef if it's not
> (ie don't die, and don't ignore what would be incomplete 'tuples' at the
> end)
>
> So if the list has 10 elements, it iterates as
>
> One Two Three
> Four Five Six
> Seven Eight Nine
> Ten undef undef
>
> and with 11, that last iteration is
>
> Ten Eleven undef
>

This was my assumption as well and seems the most reasonable thing to do.
It's consistent with regular list assignment.


> > for my ($a, $b, undef) ((1,2,3)) { … } # one iteration or syntax error--
>
> Right. This is the interesting question...
>
> I'm suggesting syntax error.
>
> I think the slightly better question would be express it as
>
> for my ($a, undef, $c) (1 .. 9) { ... }
>
>
> It's a reasonable generalisation of list assignment, where you can assign
> to
> undef to mean "ignore this value". I can see that this *might* be useful.
> It's also safe syntax to implement (although I didn't try, and I'm not sure
> how hard it would be).
>
> I'd like to stick to forbidding this, because it makes the implementation
> harder.
>

I also see how it could be useful, but on the other hand it is exactly the
same in practice as my ($x, $y, $z) but with some (imagined or real)
microoptimization of not aliasing the second value/using up that variable
name. I don't think it's useful enough to outweigh complication to the
implementation.

-Dan
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, Jun 10, 2021 at 4:20 AM Marco Fontani <fontani@gmail.com> wrote:

> > for my ($key, $value) (%hash) { ... }
>
> Could:
>
> for my ($index, $value) (@array) { ... }
>
> ... be in the cards?
>
> I always find it tiring to have to iterate by index using a weird:
>
> for my $i (0..$#array) {
> my $value = $array[$i];
> # ...
>
> ... and I'd rather the golang way (unsure if other languages have it)
> of being able to iterate either by value, or key/value for
> maps/hashes, or index/value for arrays, specifically.
>

Not likely, because this would already have the meaning of iterating over
the array 2 elements at a time. You could do something like:

foreach my ($i, $elem) (%array[0..$#array]) {

Up to you whether you think that's more understandable...

-Dan
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, 10 Jun 2021 10:20:09 +0200, Marco Fontani <fontani@gmail.com>
wrote:

> > for my ($key, $value) (%hash) { ... }
>
> Could:
>
> for my ($index, $value) (@array) { ... }
>
> ... be in the cards?
>
> I always find it tiring to have to iterate by index using a weird:
>
> for my $i (0..$#array) {
> my $value = $array[$i];
> # ...

This is already supported by `each`:

$ perl -wE'my@x="a".."f";while(my($idx,$v)=each@x){say"$idx:$v"}'
0:a
1:b
2:c
3:d
4:e
5:f

> ... and I'd rather the golang way (unsure if other languages have it)
> of being able to iterate either by value, or key/value for
> maps/hashes, or index/value for arrays, specifically.

--
H.Merijn Brand https://tux.nl Perl Monger http://amsterdam.pm.org/
using perl5.00307 .. 5.33 porting perl5 on HP-UX, AIX, and Linux
https://tux.nl/email.html http://qa.perl.org https://www.test-smoke.org
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, Jun 10, 2021 at 10:20:09AM +0200, Marco Fontani wrote:
> > for my ($key, $value) (%hash) { ... }
>
> Could:
>
> for my ($index, $value) (@array) { ... }
>
> ... be in the cards?

Not with *that* syntax, because that conflicts with general n-at-a-time.

But it's a problem that needs solving well, and I hope there will be an RFC
about it soon.

(The would-be author is currently asleep, so I can't confirm or deny
anything. I might be jumping the gun here, but there's a syntax suggestion
that builds on n-at-a-time to implement what you want. I hope I haven't
let too much slip, but I wanted to reply promptly.)

Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
From the keyboard of Dan Book [10.06.21,04:24]:

> > for my ($a, $b, undef) ((1,2,3)) { … } # one iteration or syntax error--
>
> Right. This is the interesting question...
>
> I'm suggesting syntax error.
>
> I think the slightly better question would be express it as
>
>     for my ($a, undef, $c) (1 .. 9) { ... }
>
>
> It's a reasonable generalisation of list assignment, where you can assign to
> undef to mean "ignore this value". I can see that this *might* be useful.
> It's also safe syntax to implement (although I didn't try, and I'm not sure
> how hard it would be).
>
> I'd like to stick to forbidding this, because it makes the implementation
> harder.
>
>
> I also see how it could be useful, but on the other hand it is exactly the same in practice
> as my ($x, $y, $z) but with some (imagined or real) microoptimization of not aliasing the
> second value/using up that variable name. I don't think it's useful enough to outweigh
> complication to the implementation. 

And it would introduce an exception of a general rule for little gain.
Targets for assignments must be lvalues. Assigning to undef, a literal
or a constant is prohibited.

If assigning to 'undef' in that special case is permitted, the following
should also be permitted

for my ($first, "banana", $last) (@snacks) { ... }

and so the "must be lvalue" rule would deteriorate from that end.

0--gg-

--
_($_=" "x(1<<5)."?\n".q·/)Oo. G°\ /
/\_¯/(q /
---------------------------- \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, 10 Jun 2021 08:27:54 +0000
Nicholas Clark <nick@ccl4.org> wrote:

> Not with *that* syntax, because that conflicts with general
> n-at-a-time.
>
> But it's a problem that needs solving well, and I hope there will be
> an RFC about it soon.

I've often pondered stealing Python's "enumerate" function; so that
would be


foreach my ($index, $item) (enumerate @array)
{
...
}

Where `enumerate LIST` just yields (0, LIST[0], 1, LIST[1], ...)

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, Jun 10, 2021 at 4:46 AM shmem <gm@qwurx.de> wrote:

> From the keyboard of Dan Book [10.06.21,04:24]:
>
> > > for my ($a, $b, undef) ((1,2,3)) { … } # one iteration or syntax
> error--
> >
> > Right. This is the interesting question...
> >
> > I'm suggesting syntax error.
> >
> > I think the slightly better question would be express it as
> >
> > for my ($a, undef, $c) (1 .. 9) { ... }
> >
> >
> > It's a reasonable generalisation of list assignment, where you can
> assign to
> > undef to mean "ignore this value". I can see that this *might* be
> useful.
> > It's also safe syntax to implement (although I didn't try, and I'm
> not sure
> > how hard it would be).
> >
> > I'd like to stick to forbidding this, because it makes the
> implementation
> > harder.
> >
> >
> > I also see how it could be useful, but on the other hand it is exactly
> the same in practice
> > as my ($x, $y, $z) but with some (imagined or real) microoptimization of
> not aliasing the
> > second value/using up that variable name. I don't think it's useful
> enough to outweigh
> > complication to the implementation.
>
> And it would introduce an exception of a general rule for little gain.
> Targets for assignments must be lvalues. Assigning to undef, a literal
> or a constant is prohibited.
>
> If assigning to 'undef' in that special case is permitted, the following
> should also be permitted
>
> for my ($first, "banana", $last) (@snacks) { ... }
>
> and so the "must be lvalue" rule would deteriorate from that end.


Well, it is already a special case in list assignment for this purpose,
which is probably where the idea came from:

my ($x, undef, $z) = @stuff;

But so are a bunch of other things that don't make sense in this context.

-Dan
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On 10/6/21 10:06, Nicholas Clark wrote:

>
> +### Permit `undef` in the list of scalars
> +
> + for my ($a, undef, $c) (1 .. 9) { ... }
> +
> +It's a reasonable generalisation of list assignment, where you can
assign to undef to mean "ignore this value". I can see that this
**might** be useful. It's also safe syntax to implement (although I
didn't try, and I'm not sure how hard it would be).
> +
> +But it adds considerable runtime complexity. The easiest
implementation is if there are exactly *n* scalars, all declared in the
`for` loop itself, because this way they occupy adjacent Pad slots. This
means that there is only one extra integer to store in the optree, which
used both to calculate the *n*-at-a-time **and** the addresses of the
target variables.
> +
> +Adding `undef` to the mix rules out a simple, clear implementation.

Can you just add a dummy variable there so that internally

for my ($foo, undef, $bar) (@a) {...}

is converted in something similar to

for my ($foo, $hidden_variable, $bar) (@a) {...}

?

Just for the sake of being consistent.
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, Jun 10, 2021 at 11:16:25AM +0200, Salvador Fandi?o wrote:
> On 10/6/21 10:06, Nicholas Clark wrote:
>
> >
> > +### Permit `undef` in the list of scalars
> > +
> > + for my ($a, undef, $c) (1 .. 9) { ... }
> > +
> > +It's a reasonable generalisation of list assignment, where you can assign
> to undef to mean "ignore this value". I can see that this **might** be
> useful. It's also safe syntax to implement (although I didn't try, and I'm
> not sure how hard it would be).
> > +
> > +But it adds considerable runtime complexity. The easiest implementation
> is if there are exactly *n* scalars, all declared in the `for` loop itself,
> because this way they occupy adjacent Pad slots. This means that there is
> only one extra integer to store in the optree, which used both to calculate
> the *n*-at-a-time **and** the addresses of the target variables.
> > +
> > +Adding `undef` to the mix rules out a simple, clear implementation.
>
> Can you just add a dummy variable there so that internally
>
> for my ($foo, undef, $bar) (@a) {...}
>
> is converted in something similar to
>
> for my ($foo, $hidden_variable, $bar) (@a) {...}

Yes, I think it would be possible, and probably the simplest solution.
It added complication. *I* didn't want to, as it added complication.

> ?
>
> Just for the sake of being consistent.

Yes, this is a trade off. *I* didn't think that it was worth it.
I'm not familiar enough with the grammar generally to know how to do this
easily, and I think that the optree generation would also become more
complicated.

Given that we already forbid arrays and hashes in the list of lexicals
we are declaring, it's already "inconsistent" with what my (...) = (...);
permits, so I'm not sure if we really are removing inconsistency if we
did the work to permit undef too.

Yes, this is subjective. And I might not be correct.

Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
Op 10-06-2021 om 09:28 schreef Nicholas Clark:
> On Thu, Jun 10, 2021 at 01:43:43AM +0200, Nicolas Mendoza wrote:
>> Den 08.06.2021 13:20, skrev Nicholas Clark:
>>> So, the plan for discussing the proposed RFC process was to feed an idea
>>> through it, and see how we get from idea to RFC to implementation.
>>> (Assuming that we don't reject the idea.)
>>>
>>> About two months ago Rik had mentioned to me the idea of implementing this
>>> (currently illegal) syntax to iterate over hashes:
>>>
>>> for my ($key, $value) (%hash) { ... }
>> I'm sorry if this is the wrong place to comment, but I see several comments
>> about the proposition itself, so here goes:
> No, this is totally the right place to comment.
>
> It's sensible comments like this (particularly comments from people whose
> names I don't recognise) that we'd like to see.
>
>> I really like this, it makes life simpler.
> That was what I thought when I first saw the idea. But I'm not sure if I'm
> biased. :-)
>

FWIW, I love it too. I would use this all the time. Also, it feels so
perlish, as others already said, how comes this isn't a thing yet.


HTH,

M4
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On 10/6/21 10:48, Paul "LeoNerd" Evans wrote:
> On Thu, 10 Jun 2021 08:27:54 +0000
> Nicholas Clark <nick@ccl4.org> wrote:
>
>> Not with *that* syntax, because that conflicts with general
>> n-at-a-time.
>>
>> But it's a problem that needs solving well, and I hope there will be
>> an RFC about it soon.
>
> I've often pondered stealing Python's "enumerate" function; so that
> would be
>
>
> foreach my ($index, $item) (enumerate @array)
> {
> ...
> }
>
> Where `enumerate LIST` just yields (0, LIST[0], 1, LIST[1], ...)
>

This is probably going out of control but...

How about extending "for" with attributes?

for :enumerate my ($index, $item) (@a) { ... }

for :take(4) my (@b) (@a) { ... }

for my ($key, $val) (%hash) {
# implicit :take(2) ?
}

for :enumerate ($ix, $key, $val) (%hash) { ... }

for :enumerate :take(4) my ($ix, $foo, $bar) (@a) {
# note that 2 values are discarded
# in every iteration

}
Re: RFC: Multiple-alias syntax for for [ In reply to ]
Nicholas Clark <nick@ccl4.org> wrote:
: ## Rejected Ideas
:
:+### Permit `undef` in the list of scalars
:+
:+ for my ($a, undef, $c) (1 .. 9) { ... }
:+
:+It's a reasonable generalisation of list assignment, where you can assign to undef to mean "ignore this value". I can see that this **might** be useful. It's also safe syntax to implement (although I didn't try, and I'm not sure how hard it would be).
:+
:+But it adds considerable runtime complexity. The easiest implementation is if there are exactly *n* scalars, all declared in the `for` loop itself, because this way they occupy adjacent Pad slots. This means that there is only one extra integer to store in the optree, which used both to calculate the *n*-at-a-time **and** the addresses of the target variables.
:+
:+Adding `undef` to the mix rules out a simple, clear implementation.

I'd like to add a vote for this to move from "rejected" to something
like "possible future extension", to capture the notion that "if we were
to support semantics like this, this is the syntax we'd want to use,
but we don't plan to support this for the first draft of the feature".

More generally, I think we should be slow to use "rejected" in this
context: as part of the record of an RFC process, that at least
somewhat implies "rejected for ever" - we're never going to want this
in the language. Certainly it sounds stronger than "I've chosen not
to put that in the first implementation".

(I do appreciate that all the information is there in the detail.
I just worry that labels tend to be sticky.)

The additional implication is that we should have tests in the first
implementation to assert that the extended syntax remains a syntax
error.

Hugo
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, 10 Jun 2021 14:04:59 +0200
Salvador Fandiño <sfandino@gmail.com> wrote:

> This is probably going out of control but...
>
> How about extending "for" with attributes?

I have often wanted that sort of thing (I call them "adverbs") in a
huge number of other places in perl. Far too many cases to list all of
them, but a couple of notable ones:

$str =~ s:nth(2)/foo/bar/; # substitute just the 2nd match

my @result = await map :concurrent(4) { afunc($_) } @items;

Such a thing could be an interesting idea, but it's a huge interesting
idea that involves lots of staring at lots of places, to see where and
how it might make sense.

First problem is that the syntax is too ambiguous:

map:concurrent(4)

is a call to the function &concurrent, taking the params (4), and the
statement happens to have a label `map:`. That colon notation gets in
the way alllll the time.

Annoyingly, I can't think of a good solution that doesn't start to
become whitespace-dependent; i.e. that

map: concurrent(4)

map :concurrent(4)

would need to have different meanings. And everyone is going to shoot
me for that idea.

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, Jun 10, 2021 at 9:27 AM <hv@crypt.org> wrote:

> Nicholas Clark <nick@ccl4.org> wrote:
> : ## Rejected Ideas
> :
> :+### Permit `undef` in the list of scalars
> :+
> :+ for my ($a, undef, $c) (1 .. 9) { ... }
> :+
> :+It's a reasonable generalisation of list assignment, where you can
> assign to undef to mean "ignore this value". I can see that this **might**
> be useful. It's also safe syntax to implement (although I didn't try, and
> I'm not sure how hard it would be).
> :+
> :+But it adds considerable runtime complexity. The easiest implementation
> is if there are exactly *n* scalars, all declared in the `for` loop itself,
> because this way they occupy adjacent Pad slots. This means that there is
> only one extra integer to store in the optree, which used both to calculate
> the *n*-at-a-time **and** the addresses of the target variables.
> :+
> :+Adding `undef` to the mix rules out a simple, clear implementation.
>
> I'd like to add a vote for this to move from "rejected" to something
> like "possible future extension", to capture the notion that "if we were
> to support semantics like this, this is the syntax we'd want to use,
> but we don't plan to support this for the first draft of the feature".
>
> More generally, I think we should be slow to use "rejected" in this
> context: as part of the record of an RFC process, that at least
> somewhat implies "rejected for ever" - we're never going to want this
> in the language. Certainly it sounds stronger than "I've chosen not
> to put that in the first implementation".
>
> (I do appreciate that all the information is there in the detail.
> I just worry that labels tend to be sticky.)
>
> The additional implication is that we should have tests in the first
> implementation to assert that the extended syntax remains a syntax
> error.
>

Agreed, if it is an error now, it is trivial (design wise, at least) to add
support for it later.

-Dan
Re: RFC: Multiple-alias syntax for for [ In reply to ]
> I have often wanted that sort of thing (I call them "adverbs") in a
>
> First problem is that the syntax is too ambiguous:
>
>
Syntax issues avoided on "block API" concept with "alter meta operator"

Example of multi item traversal:

for (@list) {
has $item;
...
}

for (@list) {
has $item1;
has $item2;
...
}

for (@list) {
has $item1;
has $index1 := :is => Array::index;
has $item2 := :is => Array::next;
...
}

More at
https://github.com/happy-barney/perl-poc/blob/perl-features/COP/tests/traverse-multiple-items.t

Whole concept:
https://github.com/happy-barney/perl-poc/tree/perl-features/COP

Alter meta operator - preparing standalone RFC.
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, Jun 10, 2021 at 01:54:22PM +0100, hv@crypt.org wrote:
> Nicholas Clark <nick@ccl4.org> wrote:
> : ## Rejected Ideas
> :
> :+### Permit `undef` in the list of scalars

> I'd like to add a vote for this to move from "rejected" to something
> like "possible future extension", to capture the notion that "if we were
> to support semantics like this, this is the syntax we'd want to use,
> but we don't plan to support this for the first draft of the feature".

Yes, you're right. I failed to figure this out for myself when writing that
this particular decision was "subjective" and that I might be wrong on it.

It's not the same as the other things listed below it, which (likely) we
don't want to revisit.

Paul has also reached the same conclusion thinking about try/catch as an
RFC. So it's now in a section "Future Scope"

> More generally, I think we should be slow to use "rejected" in this
> context: as part of the record of an RFC process, that at least
> somewhat implies "rejected for ever" - we're never going to want this
> in the language. Certainly it sounds stronger than "I've chosen not
> to put that in the first implementation".
>
> (I do appreciate that all the information is there in the detail.
> I just worry that labels tend to be sticky.)

Yes. Does splitting things between "Future Scope" and "Rejected Ideas"
cover this? Or do need different names for "NO WAI!!" and "Out of Scope"?

> The additional implication is that we should have tests in the first
> implementation to assert that the extended syntax remains a syntax
> error.

That's a really good point, here and generally. Thanks.

(I'd missed this line in my first skim of your message. I'm going to update
the template to suggest this.)

Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, Jun 10, 2021 at 03:08:56PM +0100, Paul "LeoNerd" Evans wrote:
> On Thu, 10 Jun 2021 14:04:59 +0200
> Salvador Fandi?o <sfandino@gmail.com> wrote:
>
> > This is probably going out of control but...
> >
> > How about extending "for" with attributes?
>
> I have often wanted that sort of thing (I call them "adverbs") in a
> huge number of other places in perl. Far too many cases to list all of
> them, but a couple of notable ones:
>
> $str =~ s:nth(2)/foo/bar/; # substitute just the 2nd match

That's also already valid syntax (well, ish):

$ perl -e '$str =~ s:nth(2)/foo/bar/;'
Substitution pattern not terminated at -e line 1.

because it's s/// but with ':' instead of '/'

Larry's 2nd Law of Language Redesign: Larry gets the colon.

I don't actually know what the 1st Law as.

However, I do know the rough backstory, and the relevant detail...

IIRC the rough backstory was that during the RFC process (and later)
*everyone* was proposing different syntax using a colon. Most of which
was mutually exclusive (ie any one person's plan blocked 6+ others...)

So Larry wanted to be clear that he got to pick the syntax that used the
colon, to get maximum value by solving as many important problems as
possible.



But, the relevant detail here is:

$perl5 ? $ternary : $operator;

$perl6 ?? $ternary !! $operator;

(spelled appropriately for the context)


For Perl, the ternary operator rules out a lot of uses of the colon because
in any expression, likely a ':' will need to be parseable as part of a
ternary.


> First problem is that the syntax is too ambiguous:
>
> map:concurrent(4)
>
> is a call to the function &concurrent, taking the params (4), and the
> statement happens to have a label `map:`. That colon notation gets in
> the way alllll the time.
>
> Annoyingly, I can't think of a good solution that doesn't start to
> become whitespace-dependent; i.e. that
>
> map: concurrent(4)
>
> map :concurrent(4)
>
> would need to have different meanings. And everyone is going to shoot
> me for that idea.

It seems calmer to run the thought experiment "What would Abigail think?"


I'd forgotten about labels. So, so far, "things that like the colon"

1) ternaries
2) labels
3) delimiters for q-like operators


Likewise, '.' works as a method call operator because concatenation became
'~', (and bitwise '~' is pushed onward...)

But the subtle part is that you also need matching became '~~'.

Without that change, you have '.=' morphing to '~=', but '=~' would still be
legal, so confusing legal syntax typos abound...


And this is part of the "Perl should stay Perl" conundrum.

1) How far can you bend syntax whilst still being understandable?
2) What existing other syntax is "getting in the way" of your good idea.


A lot of the stuff in the language-formerly-known-as-Perl-6 only works as
part of a *grand* redesign. It's difficult to cherry-pick out parts that
are unambiguously "useful to us" and "a good solution" because often they
depend on other things being changed to work well, if at all.

So adverbs starting `:` is one of these things - I think most of us think
that this is nice, obvious syntax, and we'd love to have it.

*but*

where we can use it is limited by at least 3 existing other uses of ':',
and it's not clear

1) how far that restricts it
2) whether attempting to remove those restrictions costs more than benefits

(and as ever, these are design trade offs, so different people value them
differently, and that's quite legitimate. Which just adds to the fun.)


Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, 10 Jun 2021 07:28:16 +0000
Nicholas Clark <nick@ccl4.org> wrote:

> What happens here if the list count isn't an integer multiple of 3?
>
> To me, the most obvious answer was substitute undef if it's not
> (ie don't die, and don't ignore what would be incomplete 'tuples' at
> the end)

I'd agree with that. That's also consistent with how my newly-added
List::Util::zip and ::mesh functions work; documented thus:

>> ... If any input arrays run out of elements before others, then
>> "undef" will be inserted into the result to fill in the gaps.

--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Fri, Jun 11, 2021 at 10:38:43AM +0100, Paul "LeoNerd" Evans wrote:
> On Thu, 10 Jun 2021 07:28:16 +0000
> Nicholas Clark <nick@ccl4.org> wrote:
>
> > What happens here if the list count isn't an integer multiple of 3?
> >
> > To me, the most obvious answer was substitute undef if it's not
> > (ie don't die, and don't ignore what would be incomplete 'tuples' at
> > the end)
>
> I'd agree with that. That's also consistent with how my newly-added
> List::Util::zip and ::mesh functions work; documented thus:

Good, and thanks for the confirmation that it wasn't a totally daft idea.

PEP1 has:

Finally, a proposed enhancement must be "pythonic" in order to be
accepted by the Steering Council. (However, "pythonic" is an imprecise
term; it may be defined as whatever is acceptable to the Steering
Council. This logic is intentionally circular.)


I'm guessing that we want things to be "perlish". Tentatively that seems
to be some blend of

* shown just the code, a perl programmer would guess behaviour consistent
with the documentation you actually wrote
* looks like it was always part of the language
* behaves consistently with existing similar features - easy to teach


Of course, when you start with a language with

less a design than a thousand special features flying in close formation

(I can't find the an attribution on that one)

then some of that existing behaviour is undoubtedly something that with
hindsight should have been done differently. So staying consistent with it
is repeating mistakes. You can't always win.


Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
Nicholas Clark <nick@ccl4.org> wrote:
:On Thu, Jun 10, 2021 at 01:54:22PM +0100, hv@crypt.org wrote:
:> More generally, I think we should be slow to use "rejected" in this
:> context: as part of the record of an RFC process, that at least
:> somewhat implies "rejected for ever" - we're never going to want this
:> in the language. Certainly it sounds stronger than "I've chosen not
:> to put that in the first implementation".
:
:Yes. Does splitting things between "Future Scope" and "Rejected Ideas"
:cover this? Or do need different names for "NO WAI!!" and "Out of Scope"?

I think the former is fine; the process documentation should try to make
clear how complete or permanent the rejection is.

Hugo
Re: RFC: Multiple-alias syntax for for [ In reply to ]
Rule 2 violation!

On Fri, Jun 11, 2021 at 7:32 AM <hv@crypt.org> wrote:

> Nicholas Clark <nick@ccl4.org> wrote:
> :On Thu, Jun 10, 2021 at 01:54:22PM +0100, hv@crypt.org wrote:
> :>

--
"Lay off that whiskey, and let that cocaine be!" -- Johnny Cash
Re: RFC: Multiple-alias syntax for for [ In reply to ]
Your entire message arrives as:

On Fri, Jun 11, 2021 at 09:52:59AM -0500, David Nicol wrote:
> Rule 2 violation!
>
> On Fri, Jun 11, 2021 at 7:32 AM <hv@crypt.org> wrote:
>
> > Nicholas Clark <nick@ccl4.org> wrote:
> > :On Thu, Jun 10, 2021 at 01:54:22PM +0100, hv@crypt.org wrote:
> > :>
>
> --
> "Lay off that whiskey, and let that cocaine be!" -- Johnny Cash

You don't actually quote enough for the comment to make sense to me.
I'm guessing

Rule 1: Larry is always right
Rule 2: Larry is allowed to change his mind


and a rule 2 violation would be a concept of "permanent rejection" given
that that *appears* to preclude changing one's mind.

If so, I'm not convinced that it is, because Larry (or the successor to
the BDFL, the Benevolent elected For a-term-at-a-time (in triplicate))
would change his mind (its hive-mind) when presented with new evidence,
or if re-evaluating something and discovering a mistake.

In the absence of new evidence, a competent BDFL (or hive mind) will
have feel for how confident it is that the existing decision is correct
based on the currently available evidence.


Or did I guess wrong and this is about something else?

eg - it was a *Law* of Language Redesign that Larry got the colon.
(Law 1, I found soon after mailing) was "Everyone wants the colon"
and Hugo's mailer is quoting with colons

If so, I guess this confusion is rather like:

Sturgeon's Law: "nothing is always absolutely so"
Sturgeon's Revelation: "ninety percent of everything is crap"


Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, Jun 10, 2021 at 04:24:42AM -0400, Dan Book wrote:
> On Thu, Jun 10, 2021 at 3:28 AM Nicholas Clark <nick@ccl4.org> wrote:
>
> >
> > I admit some guilt and inconsistency here - *I* preferred using `for` in
> > the code examples because it's 4 characters shorter.
> >
> > *but* I realised that that makes the title `Multiple-alias syntax for for`
> > which is daft. So I changed *that* to `foreach`. And now it's inconsistent.
> > Bad programmer, no cookie.
> >
> > I don't know what is best.
> >
>
> My preference is to refer to the syntax construct descriptively as
> "foreach", since although it is an exact synonym in the grammar, the
> C-style for loop is never referred to as a "foreach". Separately from what
> any person may decide to write in the actual code.

It turns out that this is how the docs do it. (More below)

> > I think the slightly better question would be express it as
> >
> > for my ($a, undef, $c) (1 .. 9) { ... }
> >
> >
> > It's a reasonable generalisation of list assignment, where you can assign
> > to
> > undef to mean "ignore this value". I can see that this *might* be useful.
> > It's also safe syntax to implement (although I didn't try, and I'm not sure
> > how hard it would be).
> >
> > I'd like to stick to forbidding this, because it makes the implementation
> > harder.
> >
>
> I also see how it could be useful, but on the other hand it is exactly the
> same in practice as my ($x, $y, $z) but with some (imagined or real)
> microoptimization of not aliasing the second value/using up that variable
> name. I don't think it's useful enough to outweigh complication to the
> implementation.

I think this too, but I realise that one of us might spot a good way to do
it that doesn't have much extra complication. In particular, I suspect that
if it's possible to set the Pad up the same way that anonymous entries such
as TARG slots are represented, then there might be zero runtime overhead
for "aliasing" to "undef".



So, anyway, I think that we've got to this stage:

|
v
Provisional RFC
"we think this idea is worth implementing"
(We have a firm idea of what we want to do)



There are 4 open issues that I can see, that I'm not sure about:

1) Should this be behind a feature guard?
2) Should it issue an experimental warning?
3) Are there any examples that aren't already in the *Motivation* section?
4) Are there any *Security Implications*?


Right now my test implementation doesn't guard or warn:

https://github.com/nwc10/perl5/commits/smoke-me/nicholas/pp_iter

but I think if either are needed, the "right" place is in `yyl_foreach`

I filled out the "Specification" and "Backwards Compatibility" sections.

I like the idea of the "Specification" just *being* the proposed end-user
documentation, but I'm not sure if a diff-hunk is the best way to express
this. I used one because it seemed the easiest way to say "I need to change
the Pod file in these three places, in this way". So diff and context :-)

Nicholas Clark


-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

## Specification

```
diff --git a/pod/perlsyn.pod b/pod/perlsyn.pod
index fe511f052e..490119d00e 100644
--- a/pod/perlsyn.pod
+++ b/pod/perlsyn.pod
@@ -282,6 +282,14 @@ The following compound statements may be used to control flow:

PHASE BLOCK

+As of Perl 5.36, you can iterate over multiple values at a time by specifying
+a list of lexicals within parentheses
+
+ LABEL for my (VAR, VAR) (LIST) BLOCK
+ LABEL for my (VAR, VAR) (LIST) BLOCK continue BLOCK
+ LABEL foreach my (VAR, VAR) (LIST) BLOCK
+ LABEL foreach my (VAR, VAR) (LIST) BLOCK continue BLOCK
+
If enabled by the experimental C<try> feature, the following may also be used

try BLOCK catch (VAR) BLOCK
@@ -549,6 +557,14 @@ followed by C<my>. To use this form, you must enable the C<refaliasing>
feature via C<use feature>. (See L<feature>. See also L<perlref/Assigning
to References>.)

+As of Perl 5.36, you can iterate over a list of lexical scalars n-at-a-time.
+If the size of the LIST is not an exact multiple of number of iterator
+variables, then on the last iteration the "excess" iterator variables are
+undefined values, much like if you slice beyond the end of an array. You
+can only iterate over scalars - unlike list assignment, it's not possible to
+use C<undef> to signify a value that isn't wanted. This is a limitation of
+the current implementation, and might be changed in the future.
+
Examples:

for (@ary) { s/foo/bar/ }
@@ -574,6 +590,17 @@ Examples:
# do something which each %hash
}

+ foreach my ($foo, $bar, $baz) (@list) {
+ # do something three-at-a-time
+ }
+
+ foreach my ($key, $value) (%hash) {
+ # iterate over the hash
+ # The hash is eagerly flattened to a list before the loop starts,
+ # but as ever keys are copies, values are aliases.
+ # This is the same behaviour as for $var (%hash) {...}
+ }
+
Here's how a C programmer might code up a particular algorithm in Perl:

for (my $i = 0; $i < @ary1; $i++) {
```

## Backwards Compatibility

The new syntax is a syntax error on existing Perls. It generates this error message

`Missing $ on loop variable at /home/nick/test/three-at-a-time.pl line 4.`

Existing static tooling should be able to recognise it as a syntax error, but without changes wouldn't be able to give any better diagnostics.

The proposed implementation has tests and patches for `B::Deparse` and `B::Concise`. `Devel::Cover`, `Devel::NYTProf` and `Perl::Critic` handle the new syntax just fine.

I don't think that we have any way to emulate this syntax for earlier Perls. I don't have any feel for what sort of API we would need to add to the parser to make it possible in the future, and whether any API we could add would be fragile and tightly coupled to the exact current implementation.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Mon, Jun 14, 2021 at 4:22 AM Nicholas Clark <nick@ccl4.org> wrote:

>
> I don't think that we have any way to emulate this syntax for earlier
> Perls. I don't have any feel for what sort of API we would need to add to
> the parser to make it possible in the future, and whether any API we could
> add would be fragile and tightly coupled to the exact current
> implementation.
>


this, like most all syntax extension proposals, could be done with a robust
macro system which would hook the "for" keyword and own the parser for a
few tokens. As to aliases instead of copies, it seems it would rely on
lexical aliasing unless the macro system was outputting to a deeper level
than a miniperl.



--
"Lay off that whiskey, and let that cocaine be!" -- Johnny Cash
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Mon, Jun 14, 2021 at 08:51:20AM -0500, David Nicol wrote:
> On Mon, Jun 14, 2021 at 4:22 AM Nicholas Clark <nick@ccl4.org> wrote:
>
> >
> > I don't think that we have any way to emulate this syntax for earlier
> > Perls. I don't have any feel for what sort of API we would need to add to
> > the parser to make it possible in the future, and whether any API we could
> > add would be fragile and tightly coupled to the exact current
> > implementation.
> >
>
>
> this, like most all syntax extension proposals, could be done with a robust
> macro system which would hook the "for" keyword and own the parser for a
> few tokens.

I appreciate that you're trying to make helpful suggestions, but that level
of detail is "obviously true" without giving any idea about how to implement
it. For getting to a working solution, it's about as useful as jokingly
observing that "any sufficiently advanced technology is indistinguishable
from magic". (Which, sometimes, is what the perl internals feel like.)

"macro system" - yes, sure, what one seems to need is a way to be able to
tag each keyword with "actually, don't use the regular parser here, call
me instead". So with that in place, when the parser gets to a keyword and
it's `for` it takes the "have a macro override path"

But what's down that path? Really, if we do that, we need to have a
*complete* *re-implementation* of the parsing of `for` (all the way to the
end of any `continue` block), so that we can then make arbitrary other
changes (eg, add an optional `else` block to `for` blocks).

Which means that we need a complete and correct parser. For that version of
perl. For *each* and *every* version of perl that we want to "polyfill"
back to. Because Perl C parser code changes between each release. Which
means

1) either our CPAN module has to ship copies of each and every parser
2) or we actually then have to re-write the parser so that it itself is
implemented as a macro system internally. So our "new syntax" module can
just change the macros.


Either way would be hard. Rewriting the parser - well, the lexer code is C
code. The grammar *is* a grammar, sure, but it's *compiled* to fixed C
data structures by bison, and we put *that* C into git. And that C is
compiled to fixed data structures at build time. We couldn't change Perl's
parser to be "runtime malleable" with macros (in any generic way) without
completely rewriting it *not* to use bison.


And *that* level of detail for a thought experiment might be useful. But
that's not what you wrote. And hence why it's actually not that helpful
to suggest generic broad concept ideas, particularly when the folks who
say that they are stuck have a heck of a lot more experience of the evil
horrors of the internals than you do. (You are lucky. You have no scars.)

> As to aliases instead of copies, it seems it would rely on
> lexical aliasing unless the macro system was outputting to a deeper level
> than a miniperl.

That's really actually not a problem. The C internals throw pointers to SVs
around. Aliasing and binding are trivial at the C level.

Different runtime behaviour is easy (enough) with custom OPs.

It's not really the way that you assumed that it was. The problem is really
the parser, not the runtime.

Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Mon, Jun 14, 2021 at 5:23 AM Nicholas Clark <nick@ccl4.org> wrote:

> There are 4 open issues that I can see, that I'm not sure about:
>
> 1) Should this be behind a feature guard?
>

Since the current proposed syntax has no conflicts, I don't think this is
needed.


> 2) Should it issue an experimental warning?
>

This might be prudent, regardless.

-Dan
Re: RFC: Multiple-alias syntax for for [ In reply to ]
2021-6-14 18:23 Nicholas Clark <nick@ccl4.org> wrote

>
>
> So, anyway, I think that we've got to this stage:
>
> |
> v
> Provisional RFC
> "we think this idea is worth implementing"
> (We have a firm idea of what we want to do)
>
>
I think it's good.


>
> 4) Are there any *Security Implications*?
>
>
Personally, I think this syntax doesn't affect security.
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Mon, Jun 14, 2021 at 09:22:10AM +0000, Nicholas Clark wrote:
> 2) Should it issue an experimental warning?

I think it should at least have an experimental warning, mostly as a
"coders haven't beating on the implementation for N years, there might
be bugs" warning.

Chained comparisons didn't get such a warning, and that had one
serious bug that I'm aware of (constant folding could underflow the
stack.)

Tony
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Mon, 14 Jun 2021 at 17:28, Dan Book <grinnz@gmail.com> wrote:

> On Mon, Jun 14, 2021 at 5:23 AM Nicholas Clark <nick@ccl4.org> wrote:
>
>> There are 4 open issues that I can see, that I'm not sure about:
>>
>> 1) Should this be behind a feature guard?
>>
>
> Since the current proposed syntax has no conflicts, I don't think this is
> needed.
>

Wrong

It has conflicts, with every perl before one implementing it.
Therefore it should required at least bundle specification


>
>
>> 2) Should it issue an experimental warning?
>>
>
> This might be prudent, regardless.
>
> -Dan
>
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, Jun 15, 2021 at 6:13 AM Tony Cook <tony@develop-help.com> wrote:

> On Mon, Jun 14, 2021 at 09:22:10AM +0000, Nicholas Clark wrote:
> > 2) Should it issue an experimental warning?
>
> I think it should at least have an experimental warning, mostly as a
> "coders haven't beating on the implementation for N years, there might
> be bugs" warning.
>
> Chained comparisons didn't get such a warning, and that had one
> serious bug that I'm aware of (constant folding could underflow the
> stack.)
>

I kind of think we need to have a (separate) discussion on when and
especially why we have experimental warnings.

Leon
Re: RFC: Multiple-alias syntax for for [ In reply to ]
Branislav Zahradník <happy.barney@gmail.com> writes:

> On Mon, 14 Jun 2021 at 17:28, Dan Book <grinnz@gmail.com> wrote:
>
>> On Mon, Jun 14, 2021 at 5:23 AM Nicholas Clark <nick@ccl4.org> wrote:
>>
>>> There are 4 open issues that I can see, that I'm not sure about:
>>>
>>> 1) Should this be behind a feature guard?
>>>
>>
>> Since the current proposed syntax has no conflicts, I don't think this is
>> needed.
>>
>
> Wrong
>
> It has conflicts, with every perl before one implementing it.
> Therefore it should required at least bundle specification

Of course it doesn't work on older perls that don't support the feature,
that's not what we mean by "conflict". We mean that it doesn't conflict
with (and change the meaning of) existing valid syntax.

The point of feature.pm is to be able to opt-in to behaviour or syntax
that might change the meaning of existing programs.

Ths feature does not change the behaviour of existing programs, so no
feature flag is needed. It should still have an experimental-category
warning, though.

- ilmari
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, 15 Jun 2021 at 12:09, Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>
wrote:

>
> Of course it doesn't work on older perls that don't support the feature,
> that's not what we mean by "conflict". We mean that it doesn't conflict
> with (and change the meaning of) existing valid syntax.
>
> The point of feature.pm is to be able to opt-in to behaviour or syntax
> that might change the meaning of existing programs.
>
> Ths feature does not change the behaviour of existing programs, so no
> feature flag is needed. It should still have an experimental-category
> warning, though.
>
> - ilmari
>

Be polite to your customers.

Allowing new syntax only with "use v5.xx" guard prevents situation when
your code
starts to break after OS upgrade (downgrade) on syntax error.

Hiding new syntax behind new guard says to managers (if they are listen to
they programmers)
hey, perl is not dead, there is new version, we should upgrade ... (ideally
without refactoring)

So imho message:
this is perl 5,8, you need at least 5.99 is better then "syntax error at"
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, 15 Jun 2021 13:18:29 +0200
Branislav Zahradník <happy.barney@gmail.com> wrote:

> Allowing new syntax only with "use v5.xx" guard prevents situation
> when your code
> starts to break after OS upgrade (downgrade) on syntax error.
>
> Hiding new syntax behind new guard says to managers (if they are
> listen to they programmers)
> hey, perl is not dead, there is new version, we should upgrade ...
> (ideally without refactoring)

We didn't do that with // or ->@*


$ perl5.8.9 -e 'print undef // 123'
Warning: Use of "undef" without parentheses is ambiguous at -e line 1.
Number found where operator expected at -e line 1, near "// 123"
(Missing operator before 123?)
syntax error at -e line 1, near "// 123"
Execution of -e aborted due to compilation errors.

$ perl5.10.1 -e 'print undef // 123'
123


$ perl5.22.2 -E 'say [1,2,3]->@*'
Array found where operator expected at -e line 1, near "->@*"
(Missing operator before @*?)
syntax error at -e line 1, near "->@*
"
Execution of -e aborted due to compilation errors.

$ perl5.24.4 -E 'say [1,2,3]->@*'
123



--
Paul "LeoNerd" Evans

leonerd@leonerd.org.uk | https://metacpan.org/author/PEVANS
http://www.leonerd.org.uk/ | https://www.tindie.com/stores/leonerd/
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, Jun 15, 2021, at 12:13 AM, Tony Cook wrote:
> On Mon, Jun 14, 2021 at 09:22:10AM +0000, Nicholas Clark wrote:
> > 2) Should it issue an experimental warning?
>
> I think it should at least have an experimental warning, mostly as a
> "coders haven't beating on the implementation for N years, there might
> be bugs" warning.

I think this could be marked experimental in v5.36 and, most likely, not experimental in v5.38. It would be okay, and I wouldn't object.

That said, I'll point out that "experimental" warnings are there because they might *change*, and not because they might have bugs. I don't believe we're likely to make incompatible changes with the syntax proposed, but I also think that one experimental version is a reasonable position to take. In general, though, I'd rather we just say "This feature is new and while we've tested it enough to feel good, it may have bugs not caught until it gets executed a few billion times."

--
rjbs
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, Jun 08, 2021 at 11:20:57AM +0000, Nicholas Clark wrote:
> About two months ago Rik had mentioned to me the idea of implementing this
> (currently illegal) syntax to iterate over hashes:
>
> for my ($key, $value) (%hash) { ... }
>
> which isn't actually hash specific - it generalises to N-at-a-time over any
> list.

Just throwing this out as a possible further/later extension of this idea:
allow for multiple lists, separated by semicolons, to be iterated over in
parallel, to provide a more general N-from-M iteration mechanism.

This could already be done by using a List::Util::zip() type function,
but this way would be built-in so more efficient, and doesn't involve
creating a temporary list.

So given:

@a = (1,2,3,4,5); @b = (11,22,33,44,55); @c = (111,222,333,444,555);

consider

for my ($x, $y, $z) (@a; @b; @c) { print "($x,$y,$z) " }
# outputs (1,11,111) (2,22,222) ... (5,55,555)

and

for my $x (@a; @b; @c) { print "$x " }
# outputs 1 11 111 2 22 222 ... 5 55 555

and

for my ($x, $y) (@a; @b; @c) { print "($x,$y) " }
# outputs (1,11) (111,2) (22,222) ... (5,55) (555,<undef>)

and

# just to make clear that it's 3 lists, not 3 arrays;
for my $x ((7,@a); (8,@b); (9,@c)) { print "$x " }
# outputs 7 8 9 1 11 111 2 22 222 ... 5 55 555

Obviously it would do suitable injecting of undef final values for differing
list lengths etc.

This doesn't clash with the existing

for (init; cond; iterate) { ...}

syntax, since that doesn't have an iterator variable.

Anyway, I'm not particularly championing this suggestion; just mentioning
in passing as I process through my backlog of several month's unread
p5p/github emails.


--
This is a great day for France!
-- Nixon at Charles De Gaulle's funeral
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, 22 Jun 2021 at 17:04, Dave Mitchell <davem@iabyn.com> wrote:

> On Tue, Jun 08, 2021 at 11:20:57AM +0000, Nicholas Clark wrote:
>
> So given:
>
> @a = (1,2,3,4,5); @b = (11,22,33,44,55); @c = (111,222,333,444,555);
>
> consider
>
> for my ($x, $y, $z) (@a; @b; @c) { print "($x,$y,$z) " }
> # outputs (1,11,111) (2,22,222) ... (5,55,555)
>
>
>
You can expand this idea with loop similar to Java for-each loops
and/or mix multi-alias iterators (using colon as iterator bind operator,
just to provide some kind of example)
for my ($x, $y1, $y2, $z1, $z2) ($x : (8, @a); ($y1, $y2) : %b; ($z1, $z2)
: @c)
Re: RFC: Multiple-alias syntax for for [ In reply to ]
Don't recall seeing this case discussed:

my @iters = (undef,undef); # empty list would be run-time
error!
for @iters ( @iterees) {
... # $iters[0] is alias to even iterees, $iters[1]
is alias to odd ones
# if @iters changes size, next time through it gets
that many
}




--
"Lay off that whiskey, and let that cocaine be!" -- Johnny Cash
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, Jun 22, 2021, at 2:07 PM, David Nicol wrote:
>
> Don't recall seeing this case discussed:
>
> my @iters = (undef,undef); # empty list would be run-time error!
> for @iters ( @iterees) {
> ... # $iters[0] is alias to even iterees, $iters[1] is alias to odd ones
> # if @iters changes size, next time through it gets that many
> }

It's not legal. The thing after "for" must be a parenthesized list of scalar targets.

--
rjbs
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On 6/22/21 2:58 PM, Ricardo Signes wrote:
> On Tue, Jun 22, 2021, at 2:07 PM, David Nicol wrote:
>>
>> Don't recall seeing this case discussed:
>>
>>               my @iters = (undef,undef); # empty list would be
>> run-time error!
>>               for @iters ( @iterees) {
>>                     ... #   $iters[0] is alias to even iterees,
>> $iters[1] is alias to odd ones
>>                     # if @iters changes size, next time through it
>> gets that many
>>              }
>
> It's not legal.  The thing after "for" must be a parenthesized list of
> scalar targets.
>

but an easy workaround is this (my guess):

for ( $iters[0], $iters[1] ) ( @iterees) {

or even with the expansion??:

for ( @iters[*] ) ( @iterees) {

uri
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, Jun 22, 2021 at 04:03:39PM +0100, Dave Mitchell wrote:

> Just throwing this out as a possible further/later extension of this idea:
> allow for multiple lists, separated by semicolons, to be iterated over in
> parallel, to provide a more general N-from-M iteration mechanism.

It's an interesting idea, but you can't implement it with the existing OPs.
So it would belong in its own RFC, and given that it's likely tricky to
implement, and neither you nor me are interested in implementing it, I
don't think that it would go anywhere soon.

(This isn't a "no, we must never do this" - its "I don't see much benefit
in discussing it further until it looks likely that someone would write it
in a timely fashion" combined with "and if a person with the skills and time
existed, there are other improvements that gain Perl more")

> and
>
> for my ($x, $y) (@a; @b; @c) { print "($x,$y) " }
> # outputs (1,11) (111,2) (22,222) ... (5,55) (555,<undef>)
>
> and
>
> # just to make clear that it's 3 lists, not 3 arrays;
> for my $x ((7,@a); (8,@b); (9,@c)) { print "$x " }
> # outputs 7 8 9 1 11 111 2 22 222 ... 5 55 555

Implementation wise (as you know, but most folks might not), there's
an optimisation to avoid creating a temporary list for iterating whole
arrays. So logically the first example you give ought to avoid creating
3 temporary lists, or it could get slow. Whereas the second can not.

So there's quite a lot of state and complexity needed already.

> This doesn't clash with the existing
>
> for (init; cond; iterate) { ...}
>
> syntax, since that doesn't have an iterator variable.

That's an interesting observation.

Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, Jun 22, 2021 at 03:04:31PM -0400, Uri Guttman wrote:
> On 6/22/21 2:58 PM, Ricardo Signes wrote:
> > On Tue, Jun 22, 2021, at 2:07 PM, David Nicol wrote:
> > >
> > > Don't recall seeing this case discussed:
> > >
> > > ? ? ? ? ? ? ? my?@iters = (undef,undef); # empty list would be
> > > run-time error!
> > > ? ? ? ? ? ? ? for?@iters (?@iterees) {
> > > ? ? ? ? ? ? ? ? ? ? ... #? ?$iters[0] is alias to even iterees,
> > > $iters[1] is alias to odd ones
> > > ? ? ? ? ? ? ? ? ? ? # if?@iters changes size, next time through it
> > > gets that many
> > > ? ? ? ? ? ? ?}
> >
> > It's not legal.? The thing after "for" must be a parenthesized list of
> > scalar targets.
> >
>
> but an easy workaround is this (my guess):
>
> for ( $iters[0], $iters[1] ) (?@iterees) {
>
> or even with the expansion??:
>
> for ( @iters[*] ) (?@iterees) {

None of this is easy to add to the current implementation of 1-at-a-time
foreach loops.

I'm not convinced that it's a good idea making the step size of the iteration
be dependant on the array's current size, as this feels like
action-at-a-distance.

The target(s) of a foreach loop is an alias, not an assignment - to be
consistent with this:

$ perl -E 'my $foo = "Hello"; for $foo ("Boo!") { say $foo; say \$foo } say $foo; say \$foo'
Boo!
SCALAR(0x559598381f38)
Hello
SCALAR(0x5595983721b0)

it's unclear whether the the existing *values* of the array would be what
was aliased, or the entire array.

I don't think that this discussion is heading in any direction that can
be implemented.

Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Tue, Jun 15, 2021 at 02:59:32PM -0400, Ricardo Signes wrote:
> On Tue, Jun 15, 2021, at 12:13 AM, Tony Cook wrote:
> > On Mon, Jun 14, 2021 at 09:22:10AM +0000, Nicholas Clark wrote:
> > > 2) Should it issue an experimental warning?
> >
> > I think it should at least have an experimental warning, mostly as a
> > "coders haven't beating on the implementation for N years, there might
> > be bugs" warning.
>
> I think this could be marked experimental in v5.36 and, most likely, not experimental in v5.38. It would be okay, and I wouldn't object.

So, this is catch-up from what we discussed on Friday...

Consensus seemed to be that

1) we didn't need a feature guard
2) we should have an experimental warning

which effectively has resolved the open issues.
So the (outgoing) PSC felt that we could make this state transition:

Provisional RFC
"we think this idea is worth implementing"
(We have a firm idea of what we want to do)
|
v
Accepted RFC
"we think this plan looks viable"
(There is a sane plan for how to do it)

and I have updated the RFC with all of this, and the status tables at
https://github.com/Perl/RFCs


At which point "time passes" and once I have an implementation that I
believe implements the RFC, I open a PR with it.


So, time passes...

https://github.com/Perl/perl5/pull/18925

and it's regular code review time.


I guess the reviewers ask

* does it implement what the RFC specified?

in addition to the usual

* does the code have bugs or other defects?
* on balance, does merging this give a net improvement?


(and the trial process says this is a code review decision, not a PSC
decision)

Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
The Chapel language has some interesting concepts implemented, and they all have to do with exactly what I meant in my YAPC::Zoom::2021 talk; the lanaguage has no inherent constraints on these kind of concurrent semantics. I claim this is a good thing, it just needs to be recognized and expressed clearly - particularly as it relates to the perl uniprocess.

I say that because this topic reminds me of this, as does pre-RFC for extending hash slices in an expressive way.

Since we're all students of the esoteric, here's a link to Chapel's documentation.

https://chapel-lang.org/docs/language/spec/ranges.html

I highly recommend these specs be studied. It might clarify some ideas and give genesis to new ones.

Cheers,
Brett

??????? Original Message ???????

On Wednesday, June 23rd, 2021 at 2:11 AM, Nicholas Clark <nick@ccl4.org> wrote:

> On Tue, Jun 22, 2021 at 03:04:31PM -0400, Uri Guttman wrote:
>
> > On 6/22/21 2:58 PM, Ricardo Signes wrote:
> >
> > > On Tue, Jun 22, 2021, at 2:07 PM, David Nicol wrote:
> > >
> > > > Don't recall seeing this case discussed:
> > > >
> > > > my @iters = (undef,undef); # empty list would be
> > > >
> > > > run-time error!
> > > >
> > > >               for @iters ( @iterees) {
> > > >
> > > >                     ... #   $iters[0] is alias to even iterees,
> > > >
> > > > $iters[1] is alias to odd ones
> > > >
> > > >                     # if @iters changes size, next time through it
> > > >
> > > > gets that many
> > > >
> > > >              }
> > >
> > > It's not legal.  The thing after "for" must be a parenthesized list of
> > >
> > > scalar targets.
> >
> > but an easy workaround is this (my guess):
> >
> > for ( $iters[0], $iters[1] ) ( @iterees) {
> >
> > or even with the expansion??:
> >
> > for ( @iters[*] ) ( @iterees) {
>
> None of this is easy to add to the current implementation of 1-at-a-time
>
> foreach loops.
>
> I'm not convinced that it's a good idea making the step size of the iteration
>
> be dependant on the array's current size, as this feels like
>
> action-at-a-distance.
>
> The target(s) of a foreach loop is an alias, not an assignment - to be
>
> consistent with this:
>
> $ perl -E 'my $foo = "Hello"; for $foo ("Boo!") { say $foo; say \$foo } say $foo; say \$foo'
>
> Boo!
>
> SCALAR(0x559598381f38)
>
> Hello
>
> SCALAR(0x5595983721b0)
>
> it's unclear whether the the existing values of the array would be what
>
> was aliased, or the entire array.
>
> I don't think that this discussion is heading in any direction that can
>
> be implemented.
>
> Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
I probably should have poked around more before sending this last email, but here's the actual spec:

https://chapel-lang.org/docs/language/spec/index.html

Probably of note is this, which defines it's OOP pretty clearly, I think. There are probably not a lot of surprises, but it still seems like a good skim.

https://chapel-lang.org/docs/language/spec/classes.html

Brett

??????? Original Message ???????

On Wednesday, June 23rd, 2021 at 3:33 PM, mah.kitteh via perl5-porters <perl5-porters@perl.org> wrote:

> The Chapel language has some interesting concepts implemented, and they all have to do with exactly what I meant in my YAPC::Zoom::2021 talk; the lanaguage has no inherent constraints on these kind of concurrent semantics. I claim this is a good thing, it just needs to be recognized and expressed clearly - particularly as it relates to the perl uniprocess.
>
> I say that because this topic reminds me of this, as does pre-RFC for extending hash slices in an expressive way.
>
> Since we're all students of the esoteric, here's a link to Chapel's documentation.
>
> https://chapel-lang.org/docs/language/spec/ranges.html
>
> I highly recommend these specs be studied. It might clarify some ideas and give genesis to new ones.
>
> Cheers,
>
> Brett
>
> ??????? Original Message ???????
>
> On Wednesday, June 23rd, 2021 at 2:11 AM, Nicholas Clark nick@ccl4.org wrote:
>
> > On Tue, Jun 22, 2021 at 03:04:31PM -0400, Uri Guttman wrote:
> >
> > > On 6/22/21 2:58 PM, Ricardo Signes wrote:
> > >
> > > > On Tue, Jun 22, 2021, at 2:07 PM, David Nicol wrote:
> > > >
> > > > > Don't recall seeing this case discussed:
> > > > >
> > > > > my @iters = (undef,undef); # empty list would be
> > > > >
> > > > > run-time error!
> > > > >
> > > > > for @iters ( @iterees) {
> > > > >
> > > > > ... #   $iters[0] is alias to even iterees,
> > > > >
> > > > > $iters[1] is alias to odd ones
> > > > >
> > > > > # if @iters changes size, next time through it
> > > > >
> > > > > gets that many
> > > > >
> > > > > }
> > > >
> > > > It's not legal.  The thing after "for" must be a parenthesized list of
> > > >
> > > > scalar targets.
> > >
> > > but an easy workaround is this (my guess):
> > >
> > > for ( $iters[0], $iters[1] ) ( @iterees) {
> > >
> > > or even with the expansion??:
> > >
> > > for ( @iters[*] ) ( @iterees) {
> >
> > None of this is easy to add to the current implementation of 1-at-a-time
> >
> > foreach loops.
> >
> > I'm not convinced that it's a good idea making the step size of the iteration
> >
> > be dependant on the array's current size, as this feels like
> >
> > action-at-a-distance.
> >
> > The target(s) of a foreach loop is an alias, not an assignment - to be
> >
> > consistent with this:
> >
> > $ perl -E 'my $foo = "Hello"; for $foo ("Boo!") { say $foo; say \$foo } say $foo; say \$foo'
> >
> > Boo!
> >
> > SCALAR(0x559598381f38)
> >
> > Hello
> >
> > SCALAR(0x5595983721b0)
> >
> > it's unclear whether the the existing values of the array would be what
> >
> > was aliased, or the entire array.
> >
> > I don't think that this discussion is heading in any direction that can
> >
> > be implemented.
> >
> > Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
>
> > for my ($x, $y) (@a; @b; @c) { print "($x,$y) " }
> > # outputs (1,11) (111,2) (22,222) ... (5,55) (555,<undef>)
> >
> > and
> >
> > # just to make clear that it's 3 lists, not 3 arrays;
> > for my $x ((7,@a); (8,@b); (9,@c)) { print "$x " }
> > # outputs 7 8 9 1 11 111 2 22 222 ... 5 55 555
>
> Implementation wise
>


What if the syntax were extended to generally allow semicolons within round
brackets and have that mean round-robin aliasing the pieces?

my @abc = qw/ a b c /;
my @def = qw / d e f /;
my @ott = (1,2,3);

say (@abc;@def;@ott); # would output ad1be2cf3

I'm pretty sure that's currently a syntax error. The risk is that the
common typo of using a semicolon instead of a comma within an array
expansion would no longer be a syntax error, which might lead to tricky and
subtle bugs, that might make it through testing phases, as the inner arrays
would need to have more than one element each before the reordering would
happen.

the undefs returned in the slots for the short arrays (if any) would be
magical L-values that when assigned to would extend the arrays they came
from.

Good morning.

--
"Lay off that whiskey, and let that cocaine be!" -- Johnny Cash
Re: RFC: Multiple-alias syntax for for [ In reply to ]
Den 24.06.2021 14:56, skrev David Nicol:
>
>
> >     for my ($x, $y) (@a; @b; @c) { print "($x,$y) " }
> >     # outputs (1,11) (111,2) (22,222) ... (5,55) (555,<undef>)
> >
> > and
> >
> >     # just to make clear that it's 3 lists, not 3 arrays;
> >     for my $x ((7,@a); (8,@b); (9,@c)) { print "$x " }
> >     # outputs 7 8 9 1 11 111 2 22 222  ...  5 55 555
>
> Implementation wise
>
>
>
> What if the syntax were extended to generally allow semicolons within
> round brackets and have that mean round-robin aliasing the pieces?
>
> my @abc = qw/ a b c /;
> my @def = qw / d e f /;
> my @ott = (1,2,3);
>
> say (@abc;@def;@ott); # would output ad1be2cf3
>
Initially I thought the idea was cool, but it seems to me after taking a
step back that

for my ($x,y) (zip(@a,@b,@c) { … }

and

say zip(@abc,@def,@ott);

would be much clearer in the long run?

A simple mock implementation of a core zip method (without the
multiple-alias functioning) could be:

$ perl -wle 'use List::Util; my @a = (1,2,3); @b = (qw/a b c/); sub
zip(\@+) { return map { @{ $_ } } List::Util::zip(@_); } print zip(@a,
@b); for my $x (zip(@a,@b)) { print $x }'
1a2b3c
1
a
2
b
3
c
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, Jun 24, 2021 at 07:56:53AM -0500, David Nicol wrote:
> >
> > > for my ($x, $y) (@a; @b; @c) { print "($x,$y) " }
> > > # outputs (1,11) (111,2) (22,222) ... (5,55) (555,<undef>)
> > >
> > > and
> > >
> > > # just to make clear that it's 3 lists, not 3 arrays;
> > > for my $x ((7,@a); (8,@b); (9,@c)) { print "$x " }
> > > # outputs 7 8 9 1 11 111 2 22 222 ... 5 55 555
> >
> > Implementation wise
> >
>
>
> What if the syntax were extended to generally allow semicolons within round
> brackets and have that mean round-robin aliasing the pieces?
>
> my @abc = qw/ a b c /;
> my @def = qw / d e f /;
> my @ott = (1,2,3);
>
> say (@abc;@def;@ott); # would output ad1be2cf3

Please try to stay focused. This is a thread about an RFC for `for`,
and for iterating over a single list, n-at-a-time.

Not a general syntax discussion.

(Although I approve that you're thinking about how to make syntax more
general. Good designs can be re-used, and make the language more consistent
and easier to learn. Rather too many suggested improvements are each
individual special snowflakes, with little overlap with anything else.)

`zip`ing, or whatever we'd call it, is a reasonable idea, but belongs as its
own RFC (and it's not clear to me that anyone is likely to implement it in
the near future).

Nicholas Clark
Re: RFC: Multiple-alias syntax for for [ In reply to ]
On Thu, Jun 24, 2021 at 9:30 AM Nicolas Mendoza <mendoza@pvv.ntnu.no> wrote:

> Den 24.06.2021 14:56, skrev David Nicol:
>
>
>
>> > for my ($x, $y) (@a; @b; @c) { print "($x,$y) " }
>> > # outputs (1,11) (111,2) (22,222) ... (5,55) (555,<undef>)
>> >
>> > and
>> >
>> > # just to make clear that it's 3 lists, not 3 arrays;
>> > for my $x ((7,@a); (8,@b); (9,@c)) { print "$x " }
>> > # outputs 7 8 9 1 11 111 2 22 222 ... 5 55 555
>>
>> Implementation wise
>>
>
>
> What if the syntax were extended to generally allow semicolons within
> round brackets and have that mean round-robin aliasing the pieces?
>
> my @abc = qw/ a b c /;
> my @def = qw / d e f /;
> my @ott = (1,2,3);
>
> say (@abc;@def;@ott); # would output ad1be2cf3
>
> Initially I thought the idea was cool, but it seems to me after taking a
> step back that
>
> for my ($x,y) (zip(@a,@b,@c) { … }
>
> and
>
> say zip(@abc,@def,@ott);
>
> would be much clearer in the long run?
>
> A simple mock implementation of a core zip method (without the
> multiple-alias functioning) could be:
>
> $ perl -wle 'use List::Util; my @a = (1,2,3); @b = (qw/a b c/); sub
> zip(\@+) { return map { @{ $_ } } List::Util::zip(@_); } print zip(@a, @b);
> for my $x (zip(@a,@b)) { print $x }'
> 1a2b3c
> 1
> a
> 2
> b
> 3
> c
>
>
This seems more like the mesh function from List::Util, and I see no
benefit to duplicating it to a core function.

-Dan