Date: Tue, 11 Feb 2025 18:39:39 +0000
I'm personally not a fan of finding new syntax to the exact same thing that you can already do.
range based for loops were an improvement as it removed all that boilerplate of getting interators, and maybe mess it up, and get stuck to having a name to an iterator when you are only interested in the objects in it.
But to just count numbers? It seems to be just describing ranges...
There are a couple of things that I would like to see in for loops, such as being able to initialize distinct types of objects in the init list, or to be able to constexpr unroll a parameter pack with multiple distinct types.
It's not a deal breaker, but I don't feel particularly warm towards it. It may be too much effort to standardize for little improvement.
The index could be made const, that's at least an improvement, but I you rather see a proposal to make any variable const within a scope, not just in for loop bodies.
________________________________
From: Std-Proposals <std-proposals-bounces_at_[hidden]> on behalf of Pau Miquel Montequi Hernandez via Std-Proposals <std-proposals_at_[hidden]>
Sent: Tuesday, February 11, 2025 7:04:20 PM
To: std-proposals_at_[hidden] <std-proposals_at_[hidden]>
Cc: Pau Miquel Montequi Hernandez <pau.montequi_at_[hidden]>
Subject: Re: [std-proposals] for-loops revision (simplification and new syntax)
@Andrey Semashev
Quite honestly, looping with a counter is by far not the most common kind of loops you write in real code. It is the simplest kind of loop that they teach in clases
Looping with a counter might not be the most common kind of loop written, but indeed it is the simplest kind of loop that they teach in classes. "Make simple things simple" is a good principle that improves readability and teachability of the language. Also this proposal can be seen as a way to homogenize the loops, if something looks like a range, should be iterable as a range; right now C++11's range-for loop is used for many constructs that look and behave like ranges but leave aside the most simple of them: just iterate from number A to nomber B, in my opinión this is an oversight.
As a broad overview: simple loops should be simple, for fancy complicated custom iterations we have the traditional loops.
@Jonathan Wakely
Are we really just worrying about saving a few keystrokes and typing slightly less?
Typing less is not a bad thing, the less visual noise the code has, the better for spotting typos/errors/bugs. That being said a non error-prone syntax is desirable, in my opinion the for (type variable = init : limit) is unbeatable and familiar thanks to C++11's range-for loop.
If you make the tuple solution more noisy, then you can have the precise control over types that you want:
for (auto [b,e,o] = tuple<T1,T2,T3>(...); ...)
This gets quite noisy, but it's still something that's possible today, and uses language features that are useful in more places than just for loops.
And the multiple-init 'for' loop quickly gets noisy too.
I really disliked the "use tuple" approach but I'm starting to like it tbh. Yet, it feels more familiar/natural to declare each variable in the traditional way, even if it gets noisy pretty fast.
@Filip
for ( N ) { … } // run N amount of times
Didn't think of that, looks good in my opinion.
Missatge de Jonathan Wakely <cxx_at_[hidden]<mailto:cxx_at_[hidden]>> del dia dl., 10 de febr. 2025 a les 20:20:
On Mon, 10 Feb 2025, 17:15 Pau Miquel Montequi Hernandez, <pau.montequi_at_[hidden]<mailto:pau.montequi_at_[hidden]>> wrote:
Sorry for my misunderstanding Jonathan,
Indeed "I don't want to include a header" is not a justification, it is less nowadays if we just "import std;" as a whole.
Indeed. I didn't mention that because it's easy and glib to say "modules fixes that!" but in practice most people aren't able to rely on them yet.
My point is that something different can be achieved that is not possible with the tuple approach, like assigning an explicit type to each symbol, with auto […] = std::tuple(…) we are limited to use whatever type the compiler deduces which is not always the intention.
The explicitness of for (type_a a = …; type_b b = …; type_c c = …; condition, expression) provides in my opinion more control (I want exactly this type) and sense of intentionality (I wanted this to be like that), I cannot deny that it is not ideal to pollute the for with so much noise though, we can always move variables to the enclosing scope if we don't mind giving them a bigger-than-required scope and lifetime or use the tuple approach which is less noisy but more broad.
If you make the tuple solution more noisy, then you can have the precise control over types that you want:
for (auto [b,e,o] = tuple<T1,T2,T3>(...); ...)
This gets quite noisy, but it's still something that's possible today, and uses language features that are useful in more places than just for loops.
And the multiple-init 'for' loop quickly gets noisy too.
Missatge de Jonathan Wakely <cxx_at_[hidden]<mailto:cxx_at_[hidden]>> del dia dl., 10 de febr. 2025 a les 17:46:
On Mon, 10 Feb 2025 at 16:03, Pau Miquel Montequi Hernandez <pau.montequi_at_[hidden]<mailto:pau.montequi_at_[hidden]>> wrote:
You're absolutely right! doing nothing is considerably easier than doing something :P
But afaik that's not the criteria to consider or reject proposals, maybe I'm wrong. Apart from the correct and true fact "If you include a header and write the loop 'like this' you can do the same" is there any other reason to end the discussion?
I didn't suggest the discussion should end. But I do think that avoiding the need to include a header is not a good justification for a language change.
Many C++ features exist precisely so that interesting and useful things can be done in libraries, instead of pushing more and more features into the core language.
A language feature to implicitly create a tuple-like type that can initialize a structured binding would allow you to write this without <tuple>:
for (auto [b,e,o] = ?(in, in+size, out); ...)
but it would also be usable in other places, so would give more benefit than just alternative syntax for `for` loops.
range based for loops were an improvement as it removed all that boilerplate of getting interators, and maybe mess it up, and get stuck to having a name to an iterator when you are only interested in the objects in it.
But to just count numbers? It seems to be just describing ranges...
There are a couple of things that I would like to see in for loops, such as being able to initialize distinct types of objects in the init list, or to be able to constexpr unroll a parameter pack with multiple distinct types.
It's not a deal breaker, but I don't feel particularly warm towards it. It may be too much effort to standardize for little improvement.
The index could be made const, that's at least an improvement, but I you rather see a proposal to make any variable const within a scope, not just in for loop bodies.
________________________________
From: Std-Proposals <std-proposals-bounces_at_[hidden]> on behalf of Pau Miquel Montequi Hernandez via Std-Proposals <std-proposals_at_[hidden]>
Sent: Tuesday, February 11, 2025 7:04:20 PM
To: std-proposals_at_[hidden] <std-proposals_at_[hidden]>
Cc: Pau Miquel Montequi Hernandez <pau.montequi_at_[hidden]>
Subject: Re: [std-proposals] for-loops revision (simplification and new syntax)
@Andrey Semashev
Quite honestly, looping with a counter is by far not the most common kind of loops you write in real code. It is the simplest kind of loop that they teach in clases
Looping with a counter might not be the most common kind of loop written, but indeed it is the simplest kind of loop that they teach in classes. "Make simple things simple" is a good principle that improves readability and teachability of the language. Also this proposal can be seen as a way to homogenize the loops, if something looks like a range, should be iterable as a range; right now C++11's range-for loop is used for many constructs that look and behave like ranges but leave aside the most simple of them: just iterate from number A to nomber B, in my opinión this is an oversight.
As a broad overview: simple loops should be simple, for fancy complicated custom iterations we have the traditional loops.
@Jonathan Wakely
Are we really just worrying about saving a few keystrokes and typing slightly less?
Typing less is not a bad thing, the less visual noise the code has, the better for spotting typos/errors/bugs. That being said a non error-prone syntax is desirable, in my opinion the for (type variable = init : limit) is unbeatable and familiar thanks to C++11's range-for loop.
If you make the tuple solution more noisy, then you can have the precise control over types that you want:
for (auto [b,e,o] = tuple<T1,T2,T3>(...); ...)
This gets quite noisy, but it's still something that's possible today, and uses language features that are useful in more places than just for loops.
And the multiple-init 'for' loop quickly gets noisy too.
I really disliked the "use tuple" approach but I'm starting to like it tbh. Yet, it feels more familiar/natural to declare each variable in the traditional way, even if it gets noisy pretty fast.
@Filip
for ( N ) { … } // run N amount of times
Didn't think of that, looks good in my opinion.
Missatge de Jonathan Wakely <cxx_at_[hidden]<mailto:cxx_at_[hidden]>> del dia dl., 10 de febr. 2025 a les 20:20:
On Mon, 10 Feb 2025, 17:15 Pau Miquel Montequi Hernandez, <pau.montequi_at_[hidden]<mailto:pau.montequi_at_[hidden]>> wrote:
Sorry for my misunderstanding Jonathan,
Indeed "I don't want to include a header" is not a justification, it is less nowadays if we just "import std;" as a whole.
Indeed. I didn't mention that because it's easy and glib to say "modules fixes that!" but in practice most people aren't able to rely on them yet.
My point is that something different can be achieved that is not possible with the tuple approach, like assigning an explicit type to each symbol, with auto […] = std::tuple(…) we are limited to use whatever type the compiler deduces which is not always the intention.
The explicitness of for (type_a a = …; type_b b = …; type_c c = …; condition, expression) provides in my opinion more control (I want exactly this type) and sense of intentionality (I wanted this to be like that), I cannot deny that it is not ideal to pollute the for with so much noise though, we can always move variables to the enclosing scope if we don't mind giving them a bigger-than-required scope and lifetime or use the tuple approach which is less noisy but more broad.
If you make the tuple solution more noisy, then you can have the precise control over types that you want:
for (auto [b,e,o] = tuple<T1,T2,T3>(...); ...)
This gets quite noisy, but it's still something that's possible today, and uses language features that are useful in more places than just for loops.
And the multiple-init 'for' loop quickly gets noisy too.
Missatge de Jonathan Wakely <cxx_at_[hidden]<mailto:cxx_at_[hidden]>> del dia dl., 10 de febr. 2025 a les 17:46:
On Mon, 10 Feb 2025 at 16:03, Pau Miquel Montequi Hernandez <pau.montequi_at_[hidden]<mailto:pau.montequi_at_[hidden]>> wrote:
You're absolutely right! doing nothing is considerably easier than doing something :P
But afaik that's not the criteria to consider or reject proposals, maybe I'm wrong. Apart from the correct and true fact "If you include a header and write the loop 'like this' you can do the same" is there any other reason to end the discussion?
I didn't suggest the discussion should end. But I do think that avoiding the need to include a header is not a good justification for a language change.
Many C++ features exist precisely so that interesting and useful things can be done in libraries, instead of pushing more and more features into the core language.
A language feature to implicitly create a tuple-like type that can initialize a structured binding would allow you to write this without <tuple>:
for (auto [b,e,o] = ?(in, in+size, out); ...)
but it would also be usable in other places, so would give more benefit than just alternative syntax for `for` loops.
-- Pablo Miguel Montequi Hernández. -- Pablo Miguel Montequi Hernández.
Received on 2025-02-11 18:39:47