digitalmars.D - foreach
- Manu via Digitalmars-d (9/9) Jun 12 2014 I often find myself wanting to write this:
- Meta (8/19) Jun 12 2014 It's not really a workaround, but you can do:
- simendsjo (4/16) Jun 12 2014 _ is an often used identifier for "i don't care" in many languages. The
- monarch_dodra (6/10) Jun 12 2014 One issue is that "_" is still an actual identifier, with normal
- simendsjo (5/18) Jun 12 2014 Yeah, not good. Does any sane person use _ as a variable identifier and
- Rene Zwanenburg (4/11) Jun 12 2014 Even if it wouldn't break any code, special rules are bad.
- Nick Treleaven (8/26) Jun 12 2014 That might be a more flexible solution, because there is also this usage...
- bearophile (6/10) Jun 12 2014 I think this is a very uncommon usage. I think I have not used it
- Nick Treleaven (11/15) Jun 12 2014 Perhaps with something other than a range then. There are some uses in
- Nick Treleaven (13/29) Jun 14 2014 Because _ is not a language feature, this identifier is actually less
- JR (5/11) Jun 13 2014 Would enforcing immutability there be a breaking change?
- Timon Gehr (2/7) Jun 13 2014 Have you ever used void[0][T]?
- bearophile (4/5) Jun 14 2014 I have never used that so far. What is it useful for?
- Timon Gehr (2/7) Jun 14 2014 It's a hash set with a somewhat awkward interface.
- Demetri (3/28) Jun 12 2014 An identifier could be chosen that started with two underscores.
- Nick Treleaven (9/11) Jun 13 2014 I forgot that C gettext has a macro called _(), and this D version also
- monarch_dodra (3/14) Jun 13 2014 C++ also recently defined some std::placeholders, which are _1,
- bearophile (5/7) Jun 12 2014 I agree.
- monarch_dodra (3/10) Jun 12 2014 Enhancement request filed last year:
- Steven Schveighoffer (15/24) Jun 12 2014 The compiler has to assign a variable to this somehow so it can incremen...
- H. S. Teoh via Digitalmars-d (12/23) Jun 12 2014 A variable doesn't require a name, if user code never references it. All
- Ary Borenszweig (2/20) Jun 12 2014 The compiler needs a variable. The programmer doesn't.
- Steven Schveighoffer (7/31) Jun 12 2014 In response to both you and HS Teoh, so what? It's not hard to create a ...
- Andrew Edwards (11/43) Jun 12 2014 Steven, there is not one thing that makes D great. There are many.
- Steven Schveighoffer (20/68) Jun 12 2014 Sorry, saving 1-2 characters typing is really minor. This does not, in m...
- Nick Sabalausky (6/24) Jun 12 2014 While I agree on its triviality, I really doubt there's much "weight" to...
- monarch_dodra (11/13) Jun 12 2014 For what it's worth, if any work is done on foreach, +1000 I
- Steven Schveighoffer (5/16) Jun 12 2014 I don't think it's as trivial as you imply. You have to use a symbol
- Timon Gehr (4/8) Jun 12 2014 Why would implicit local variables need unique names? This can be
- Steven Schveighoffer (5/15) Jun 12 2014 Of course, it doesn't HAVE to be that way. I would think it would be
- Nick Sabalausky (3/13) Jun 12 2014 Well, s/triviality/limited importance/
- Ary Borenszweig (4/22) Jun 12 2014 You normally do that by using names that the grammar doesn't allow as
- Nick Sabalausky (2/5) Jun 12 2014 And doesn't DMD *already* do a lot of that sorta thing already?
- Ary Borenszweig (5/11) Jun 13 2014 That's why it surprises me that adding such a trivial feature is not
- Daniel Murphy (4/6) Jun 12 2014 It is trivial, the frontend already has the ability to generate new uniq...
- Nick Sabalausky (3/12) Jun 12 2014 I can't imagine this has ever been a significant issue for anyone. But
- Ary Borenszweig (14/29) Jun 12 2014 In Ruby/Crystal you can do:
- Sebastiaan Koppe (5/19) Jun 12 2014 If you give me complete requirements, proper planning, effective
- Nick Sabalausky (9/40) Jun 12 2014 No.
- Jacob Carlborg (7/9) Jun 13 2014 I use the "n.times" in Ruby for testing quite a lot. When I need to
- Daniel =?UTF-8?B?S296w6Fr?= via Digitalmars-d (4/43) Jun 12 2014 No problem for me:
- Craig Dillabaugh (3/6) Jun 12 2014 That is sweet. Well done.
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (9/11) Jun 13 2014 Would be nice if we could elide the parentheses and semicolons:
- Jacob Carlborg (4/11) Jun 13 2014 Yeah, that has been suggested before.
- Sean Kelly (3/5) Jun 13 2014 Now put a break statement in the loop body.
- Manu via Digitalmars-d (13/29) Jun 12 2014 It gets awkward when you nest, using '_' leads to '__', and
- Daniel Murphy (7/19) Jun 12 2014 i,j,k,etc work just fine. Are you really nesting your loops that deeply...
- Steven Schveighoffer (13/29) Jun 12 2014 In this case, it's being "used" but not by the user. The comparison and ...
- Manu via Digitalmars-d (13/35) Jun 12 2014 The compiler doesn't use the result of front().
- Steven Schveighoffer (10/51) Jun 12 2014 foreach(x; 0..5) translates to for(auto x = 0; x < 5; ++x)
- Manu via Digitalmars-d (11/14) Jun 12 2014 That's inefficient, I might as well perform the iteration while I'm
- Steven Schveighoffer (15/31) Jun 13 2014 It's the same complexity, O(n). I'm not sure how inefficient it is.
- Manu via Digitalmars-d (14/33) Jun 12 2014 Giving explicit names pollutes the local namespace, and the point
- Steven Schveighoffer (14/28) Jun 12 2014 i, j, k are traditionally loop variables. People have been using them fo...
- Manu via Digitalmars-d (8/39) Jun 12 2014 walkLength might not be known ahead of time. Lists?
- Steven Schveighoffer (9/58) Jun 12 2014 walkLength is for ranges you don't know the length ahead of time. It
- Jonathan M Davis via Digitalmars-d (12/23) Jun 12 2014 I don't expect that to ever happen in D. There are too many places where
- Mason McGill (13/24) Jun 12 2014 Seems like a nice idea. Especially useful when it comes to
- Jacob Carlborg (7/16) Jun 13 2014 The only reason I can see to make this change is to make it more
- Dicebot (4/15) Jun 13 2014 Over 50 comments about minor syntax issue that makes no practical
- Timon Gehr (2/3) Jun 13 2014 Including yours.
- Dicebot (2/5) Jun 13 2014 That was my first comment in this thread :O
- Rikki Cattermole (38/47) Jun 13 2014 Of course my reaction is a library solution:
- bearophile (46/46) Jun 14 2014 The idea of using code like this (only one or the other should be
I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile. You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.
Jun 12 2014
On Thursday, 12 June 2014 at 15:00:20 UTC, Manu via Digitalmars-d wrote:I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile. You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.It's not really a workaround, but you can do: foreach (_; 0..n) { //Do stuff } But it still declares a loop variable.
Jun 12 2014
On 06/12/2014 05:00 PM, Manu via Digitalmars-d wrote:I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile. You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused._ is an often used identifier for "i don't care" in many languages. The following works: foreach(_; 0..n)
Jun 12 2014
On Thursday, 12 June 2014 at 15:09:51 UTC, simendsjo wrote:_ is an often used identifier for "i don't care" in many languages. The following works: foreach(_; 0..n)One issue is that "_" is still an actual identifier, with normal name collision rules. So that works only once. When you nest your loops, you'll end up having conflicts, and name your "i don't care variable" things such as "_", "__", "___", "_1", "_2" etc... It actually happens quite often I find.
Jun 12 2014
On 06/12/2014 05:46 PM, monarch_dodra wrote:On Thursday, 12 June 2014 at 15:09:51 UTC, simendsjo wrote:Yeah, not good. Does any sane person use _ as a variable identifier and then reference it? A breaking change would be a special rule so _ can never be used and is allowed to shadow. Of course - this could break existing code, so it will never happen :)_ is an often used identifier for "i don't care" in many languages. The following works: foreach(_; 0..n)One issue is that "_" is still an actual identifier, with normal name collision rules. So that works only once. When you nest your loops, you'll end up having conflicts, and name your "i don't care variable" things such as "_", "__", "___", "_1", "_2" etc... It actually happens quite often I find.
Jun 12 2014
On Thursday, 12 June 2014 at 15:56:17 UTC, simendsjo wrote:Yeah, not good. Does any sane person use _ as a variable identifier and then reference it? A breaking change would be a special rule so _ can never be used and is allowed to shadow. Of course - this could break existing code, so it will never happen :)Even if it wouldn't break any code, special rules are bad. Enhancing foreach so the loop counter can be omitted is be better IMO. Consistent with for(;;), and avoids a special rule.
Jun 12 2014
On 12/06/2014 16:57, simendsjo wrote:On 06/12/2014 05:46 PM, monarch_dodra wrote:That might be a more flexible solution, because there is also this usage: foreach (i, _; range){...} I wonder if there may be other cases where '_' would be useful. Potentially, there's also tuple unpacking syntax: auto (v, _) = myTuple; // throw away second elementOn Thursday, 12 June 2014 at 15:09:51 UTC, simendsjo wrote:Yeah, not good. Does any sane person use _ as a variable identifier and then reference it? A breaking change would be a special rule so _ can never be used and is allowed to shadow._ is an often used identifier for "i don't care" in many languages. The following works: foreach(_; 0..n)One issue is that "_" is still an actual identifier, with normal name collision rules. So that works only once. When you nest your loops, you'll end up having conflicts, and name your "i don't care variable" things such as "_", "__", "___", "_1", "_2" etc... It actually happens quite often I find.Of course - this could break existing code, so it will never happen :)I think we can break existing code if it's bad code. Using '_' as a variable name could be considered bad enough to disallow.
Jun 12 2014
Nick Treleaven:there is also this usage: foreach (i, _; range){...}I think this is a very uncommon usage. I think I have not used it so far.Potentially, there's also tuple unpacking syntax: auto (v, _) = myTuple; // throw away second elementThis is a very important usage. Worthing breaking D2 on. Bye, bearophile
Jun 12 2014
On 12/06/2014 17:59, bearophile wrote:Perhaps with something other than a range then. There are some uses in Phobos: std/algorithm.d: foreach (i, _; args) std/exception.d: foreach (index, _; FieldTypeTuple!C) std/typecons.d: foreach (i, _; Tup1.Types) std/typecons.d: foreach (i, _; Tup1.Types) std/typecons.d: foreach (i, _; Types) // Rely on the field layout std/typecons.d: foreach (i, _; Types) std/variant.d: foreach (i, _; params)there is also this usage: foreach (i, _; range){...}I think this is a very uncommon usage. I think I have not used it so far.
Jun 12 2014
On 12/06/2014 18:30, Nick Treleaven wrote:On 12/06/2014 17:59, bearophile wrote:Because _ is not a language feature, this identifier is actually less common. The prevailing one in Phobos is: foreach (i, Unused; ...) std/algorithm.d:7 std/array.d:1 std/datetime.d:1 std/parallelism.d:2 std/range.d:28 std/typecons.d:3 This is actually used more than any uses of 'foreach (_;' (2 uses) or 'foreach (Unused;' (10 uses) in Phobos! This is true even if we treat std.range as an anomaly. (I also tried a case-insensitive search).Perhaps with something other than a range then. There are some uses in Phobos: std/algorithm.d: foreach (i, _; args) std/exception.d: foreach (index, _; FieldTypeTuple!C) std/typecons.d: foreach (i, _; Tup1.Types) std/typecons.d: foreach (i, _; Tup1.Types) std/typecons.d: foreach (i, _; Types) // Rely on the field layout std/typecons.d: foreach (i, _; Types) std/variant.d: foreach (i, _; params)there is also this usage: foreach (i, _; range){...}I think this is a very uncommon usage. I think I have not used it so far.
Jun 14 2014
On Thursday, 12 June 2014 at 16:59:34 UTC, bearophile wrote:Nick Treleaven:Would enforcing immutability there be a breaking change? foreach (/*immutable*/ i; _; range) { version(none) i = 0; }there is also this usage: foreach (i, _; range){...}I think this is a very uncommon usage. I think I have not used it so far.
Jun 13 2014
On 06/12/2014 06:59 PM, bearophile wrote:Nick Treleaven:Have you ever used void[0][T]?there is also this usage: foreach (i, _; range){...}I think this is a very uncommon usage. I think I have not used it so far.
Jun 13 2014
Timon Gehr:Have you ever used void[0][T]?I have never used that so far. What is it useful for? Bye, bearophile
Jun 14 2014
On 06/14/2014 05:33 PM, bearophile wrote:Timon Gehr:It's a hash set with a somewhat awkward interface.Have you ever used void[0][T]?I have never used that so far. What is it useful for? Bye, bearophile
Jun 14 2014
On Thursday, 12 June 2014 at 15:56:17 UTC, simendsjo wrote:On 06/12/2014 05:46 PM, monarch_dodra wrote:An identifier could be chosen that started with two underscores. Those are already reserved.On Thursday, 12 June 2014 at 15:09:51 UTC, simendsjo wrote:Yeah, not good. Does any sane person use _ as a variable identifier and then reference it? A breaking change would be a special rule so _ can never be used and is allowed to shadow. Of course - this could break existing code, so it will never happen :)_ is an often used identifier for "i don't care" in many languages. The following works: foreach(_; 0..n)One issue is that "_" is still an actual identifier, with normal name collision rules. So that works only once. When you nest your loops, you'll end up having conflicts, and name your "i don't care variable" things such as "_", "__", "___", "_1", "_2" etc... It actually happens quite often I find.
Jun 12 2014
On 12/06/2014 16:57, simendsjo wrote:Does any sane person use _ as a variable identifier and then reference it?I forgot that C gettext has a macro called _(), and this D version also has it (which is available via dub): https://github.com/NCrashed/dtext/blob/master/source/dtext.d#L115 string getdtext(string s, string locale = ""){...} /// Short name for getdtext alias getdtext _; ... writeln(_("Hello, world!"));
Jun 13 2014
On Friday, 13 June 2014 at 15:18:52 UTC, Nick Treleaven wrote:On 12/06/2014 16:57, simendsjo wrote:C++ also recently defined some std::placeholders, which are _1, _2 through _N.Does any sane person use _ as a variable identifier and then reference it?I forgot that C gettext has a macro called _(), and this D version also has it (which is available via dub): https://github.com/NCrashed/dtext/blob/master/source/dtext.d#L115 string getdtext(string s, string locale = ""){...} /// Short name for getdtext alias getdtext _; ... writeln(_("Hello, world!"));
Jun 13 2014
Manu:I see no need to declare a superfluous loop counter when it is unused.I agree. What's Walter opinion on this? Bye, bearophile
Jun 12 2014
On Thursday, 12 June 2014 at 15:14:44 UTC, bearophile wrote:Manu:Enhancement request filed last year: https://issues.dlang.org/show_bug.cgi?id=9009I see no need to declare a superfluous loop counter when it is unused.I agree. What's Walter opinion on this? Bye, bearophile
Jun 12 2014
On Thu, 12 Jun 2014 11:00:11 -0400, Manu via Digitalmars-d <digitalmars-d puremagic.com> wrote:I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile.The compiler has to assign a variable to this somehow so it can increment and test. Naming it isn't the worst thing in the world. As others have said, pick an uncommon name.You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.But that doesn't increment a variable and test it. If you wanted to loop for N times, you need a variable. You have to give it a name, it doesn't seem worth adding a feature to save that little bit of thinking. The thing about it is, you don't need to type more than is necessary: foreach(L1; 0..n) { foreach(L2; 0..n) { } } Doesn't seem that bad to me. -Steve
Jun 12 2014
On Thu, Jun 12, 2014 at 01:11:12PM -0400, Steven Schveighoffer via Digitalmars-d wrote:On Thu, 12 Jun 2014 11:00:11 -0400, Manu via Digitalmars-d <digitalmars-d puremagic.com> wrote:A variable doesn't require a name, if user code never references it. All the compiler cares about is that a symbol is created for it, that can be used when generating the loop condition code. Anonymous functions don't have names either, and the compiler handles that just fine. (Well, OK, an internal unique identifier is generated for it, but that's essentially what's being asked for here by the OP.) Or, for that matter, ignored function arguments: void delegate(int) dg = (int) { // Name not needed for ignored argument here. }; --TI often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile.The compiler has to assign a variable to this somehow so it can increment and test. Naming it isn't the worst thing in the world. As others have said, pick an uncommon name.
Jun 12 2014
On 6/12/14, 2:11 PM, Steven Schveighoffer wrote:On Thu, 12 Jun 2014 11:00:11 -0400, Manu via Digitalmars-d <digitalmars-d puremagic.com> wrote:The compiler needs a variable. The programmer doesn't.I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile.The compiler has to assign a variable to this somehow so it can increment and test. Naming it isn't the worst thing in the world. As others have said, pick an uncommon name.You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.But that doesn't increment a variable and test it. If you wanted to loop for N times, you need a variable.
Jun 12 2014
On Thu, 12 Jun 2014 13:36:20 -0400, Ary Borenszweig <ary esperanto.org.ar> wrote:On 6/12/14, 2:11 PM, Steven Schveighoffer wrote:In response to both you and HS Teoh, so what? It's not hard to create a variable, just do it. This seems like the most insignificant time-saving feature that will really have almost no impact on anybody. It's not worth the risk it adds some bug to the compiler to add this feature. -SteveOn Thu, 12 Jun 2014 11:00:11 -0400, Manu via Digitalmars-d <digitalmars-d puremagic.com> wrote:The compiler needs a variable. The programmer doesn't.I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile.The compiler has to assign a variable to this somehow so it can increment and test. Naming it isn't the worst thing in the world. As others have said, pick an uncommon name.You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.But that doesn't increment a variable and test it. If you wanted to loop for N times, you need a variable.
Jun 12 2014
On 6/12/14, 2:40 PM, Steven Schveighoffer wrote:On Thu, 12 Jun 2014 13:36:20 -0400, Ary Borenszweig <ary esperanto.org.ar> wrote:Steven, there is not one thing that makes D great. There are many. Dissected and viewed individually most people would regard the insignificant: much like you are doing here. But the aggregated whole that is D today, is a thing of beauty. And it wouldn't be that way were it if not for these ostensibly trifling features. While I do not see this as a showstopper for anyone, including, it doesn't warrant such vehement attack. It is a convenience feature that improves the overall experience of the D programmer. A plus in my mind and worthy of the time required to discuss, agree upon a solution and implement.On 6/12/14, 2:11 PM, Steven Schveighoffer wrote:In response to both you and HS Teoh, so what? It's not hard to create a variable, just do it. This seems like the most insignificant time-saving feature that will really have almost no impact on anybody. It's not worth the risk it adds some bug to the compiler to add this feature. -SteveOn Thu, 12 Jun 2014 11:00:11 -0400, Manu via Digitalmars-d <digitalmars-d puremagic.com> wrote:The compiler needs a variable. The programmer doesn't.I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile.The compiler has to assign a variable to this somehow so it can increment and test. Naming it isn't the worst thing in the world. As others have said, pick an uncommon name.You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.But that doesn't increment a variable and test it. If you wanted to loop for N times, you need a variable.
Jun 12 2014
On Thu, 12 Jun 2014 14:55:52 -0400, Andrew Edwards <ridimz yahoo.com> wrote:On 6/12/14, 2:40 PM, Steven Schveighoffer wrote:Sorry, saving 1-2 characters typing is really minor. This does not, in my opinion of course, have any significant improvement on usability for D. It simply does not carry it's own weight, and the potential to create bugs in the foreach handling would be not worth the risk. Typically, one uses i,j,k, etc for loops indexes. It's not so much more difficult to do foreach(i;... vs. foreach(;...On Thu, 12 Jun 2014 13:36:20 -0400, Ary Borenszweig <ary esperanto.org.ar> wrote:Steven, there is not one thing that makes D great. There are many. Dissected and viewed individually most people would regard the insignificant: much like you are doing here. But the aggregated whole that is D today, is a thing of beauty. And it wouldn't be that way were it if not for these ostensibly trifling features.On 6/12/14, 2:11 PM, Steven Schveighoffer wrote:In response to both you and HS Teoh, so what? It's not hard to create a variable, just do it. This seems like the most insignificant time-saving feature that will really have almost no impact on anybody. It's not worth the risk it adds some bug to the compiler to add this feature. -SteveOn Thu, 12 Jun 2014 11:00:11 -0400, Manu via Digitalmars-d <digitalmars-d puremagic.com> wrote:The compiler needs a variable. The programmer doesn't.I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile.The compiler has to assign a variable to this somehow so it can increment and test. Naming it isn't the worst thing in the world. As others have said, pick an uncommon name.You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.But that doesn't increment a variable and test it. If you wanted to loop for N times, you need a variable.While I do not see this as a showstopper for anyone, including, it doesn't warrant such vehement attack. It is a convenience feature that improves the overall experience of the D programmer. A plus in my mind and worthy of the time required to discuss, agree upon a solution and implement.It's not an attack of any kind, it's just a rebuttal. It in no way reflects on the proposer or the defenders of the proposal. If there is some significant improvement to be shown, I happily would reconsider my position. Can you name a place where the improvement is more than just saving the typing of 'i', 'j', or 'k'? There are hundreds of such proposals made for D, and many of them are rejected due to the lack of improvement to the language. This is not a unique situation. The bar must be set high for new features, or we would have a mess of a language. I will note obviously that I do not have the final say anyway. It's just my opinion. -Steve
Jun 12 2014
On 6/12/2014 3:10 PM, Steven Schveighoffer wrote:Sorry, saving 1-2 characters typing is really minor. This does not, in my opinion of course, have any significant improvement on usability for D. It simply does not carry it's own weight, and the potential to create bugs in the foreach handling would be not worth the risk.While I agree on its triviality, I really doubt there's much "weight" to speak of either. Hara probably could've already implemented and tested this in the same amount of time any *one* of us have already spent bikeshedding it.FWIW: I think this can be viewed more as "Lifting undue restrictions".While I do not see this as a showstopper for anyone, including, it doesn't warrant such vehement attack. It is a convenience feature that improves the overall experience of the D programmer. A plus in my mind and worthy of the time required to discuss, agree upon a solution and implement.It's not an attack of any kind, it's just a rebuttal. It in no way reflects on the proposer or the defenders of the proposal. If there is some significant improvement to be shown, I happily would reconsider my position. Can you name a place where the improvement is more than just saving the typing of 'i', 'j', or 'k'? There are hundreds of such proposals made for D, and many of them are rejected due to the lack of improvement to the language. This is not a unique situation. The bar must be set high for new features, or we would have a mess of a language.
Jun 12 2014
On Thursday, 12 June 2014 at 19:26:47 UTC, Nick Sabalausky wrote:FWIW: I think this can be viewed more as "Lifting undue restrictions".For what it's worth, if any work is done on foreach, +1000 I think we should tackle the "important" issues first, such as: auto ref for foreach loops https://issues.dlang.org/show_bug.cgi?id=4707 https://issues.dlang.org/show_bug.cgi?id=10541 using ref foreach parameters with std.range.zip is a no-op Allow `ref` in `foreach` over range iff `front` returns by `ref` https://issues.dlang.org/show_bug.cgi?id=11934 Once foreach is something with can work correctly and reliably, then we can add the finishing touches (IMO)
Jun 12 2014
On Thu, 12 Jun 2014 15:26:31 -0400, Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> wrote:On 6/12/2014 3:10 PM, Steven Schveighoffer wrote:I don't think it's as trivial as you imply. You have to use a symbol that's valid, but isn't used in the subsequent loop to avoid collisions. -SteveSorry, saving 1-2 characters typing is really minor. This does not, in my opinion of course, have any significant improvement on usability for D. It simply does not carry it's own weight, and the potential to create bugs in the foreach handling would be not worth the risk.While I agree on its triviality, I really doubt there's much "weight" to speak of either. Hara probably could've already implemented and tested this in the same amount of time any *one* of us have already spent bikeshedding it.
Jun 12 2014
On 06/12/2014 10:06 PM, Steven Schveighoffer wrote:Why would implicit local variables need unique names? This can be implemented by preventing identifiers named '_' to be inserted into the symbol table.I don't think it's as trivial as you imply. You have to use a symbol that's valid, but isn't used in the subsequent loop to avoid collisions. -Steve
Jun 12 2014
On Thu, 12 Jun 2014 17:41:36 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:On 06/12/2014 10:06 PM, Steven Schveighoffer wrote:Of course, it doesn't HAVE to be that way. I would think it would be easier to implement. I don't know enough to judge which is easiest, but it doesn't sound trivial either way. -SteveWhy would implicit local variables need unique names? This can be implemented by preventing identifiers named '_' to be inserted into the symbol table.I don't think it's as trivial as you imply. You have to use a symbol that's valid, but isn't used in the subsequent loop to avoid collisions. -Steve
Jun 12 2014
On 6/12/2014 4:06 PM, Steven Schveighoffer wrote:On Thu, 12 Jun 2014 15:26:31 -0400, Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> wrote:Well, s/triviality/limited importance/ Slightly inaccurate word choice, whatever ;)While I agree on its triviality, I really doubt there's much "weight" to speak of either. Hara probably could've already implemented and tested this in the same amount of time any *one* of us have already spent bikeshedding it.I don't think it's as trivial as you imply. You have to use a symbol that's valid, but isn't used in the subsequent loop to avoid collisions.
Jun 12 2014
On 6/12/14, 5:06 PM, Steven Schveighoffer wrote:On Thu, 12 Jun 2014 15:26:31 -0400, Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> wrote:You normally do that by using names that the grammar doesn't allow as valid identifiers. Then you have a counter and prepend that. This way you never have name collisions.On 6/12/2014 3:10 PM, Steven Schveighoffer wrote:I don't think it's as trivial as you imply. You have to use a symbol that's valid, but isn't used in the subsequent loop to avoid collisions. -SteveSorry, saving 1-2 characters typing is really minor. This does not, in my opinion of course, have any significant improvement on usability for D. It simply does not carry it's own weight, and the potential to create bugs in the foreach handling would be not worth the risk.While I agree on its triviality, I really doubt there's much "weight" to speak of either. Hara probably could've already implemented and tested this in the same amount of time any *one* of us have already spent bikeshedding it.
Jun 12 2014
On 6/12/2014 8:36 PM, Ary Borenszweig wrote:You normally do that by using names that the grammar doesn't allow as valid identifiers. Then you have a counter and prepend that. This way you never have name collisions.And doesn't DMD *already* do a lot of that sorta thing already?
Jun 12 2014
On 6/12/14, 9:41 PM, Nick Sabalausky wrote:On 6/12/2014 8:36 PM, Ary Borenszweig wrote:That's why it surprises me that adding such a trivial feature is not done because it can lead to many bugs. You have a regressions test suite. Plus it's really trivial: if there's no loop variable, just define one automatically.You normally do that by using names that the grammar doesn't allow as valid identifiers. Then you have a counter and prepend that. This way you never have name collisions.And doesn't DMD *already* do a lot of that sorta thing already?
Jun 13 2014
"Steven Schveighoffer" wrote in message news:op.xhcx4cb9eav7ka stevens-macbook-pro-2.local...I don't think it's as trivial as you imply. You have to use a symbol that's valid, but isn't used in the subsequent loop to avoid collisions.It is trivial, the frontend already has the ability to generate new unique identifiers. But I also don't think it's worth doing.
Jun 12 2014
On 6/12/2014 11:00 AM, Manu via Digitalmars-d wrote:I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile. You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.I can't imagine this has ever been a significant issue for anyone. But that said, I certainly can't disagree with it, and wouldn't object to it.
Jun 12 2014
On 6/12/14, 3:04 PM, Nick Sabalausky wrote:On 6/12/2014 11:00 AM, Manu via Digitalmars-d wrote:In Ruby/Crystal you can do: n.times do end In D you have to write: for(unused; 0..n) { } Doesn't it bother you that your language requires more typing and defining dummy variables just for doing something N times? Note, I'm just trying to point out that small improvements in the programmers life will be thanked a lot and more people will join your language.I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile. You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.I can't imagine this has ever been a significant issue for anyone. But that said, I certainly can't disagree with it, and wouldn't object to it.
Jun 12 2014
On Thursday, 12 June 2014 at 18:33:38 UTC, Ary Borenszweig wrote:On 6/12/14, 3:04 PM, Nick Sabalausky wrote: In Ruby/Crystal you can do: n.times do end In D you have to write: for(unused; 0..n) { } Doesn't it bother you that your language requires more typing and defining dummy variables just for doing something N times? Note, I'm just trying to point out that small improvements in the programmers life will be thanked a lot and more people will join your language.If you give me complete requirements, proper planning, effective communication, automated testing, fast compilation and a proper chair, I will program anything in the most horrid language you can think of.
Jun 12 2014
On 6/12/2014 2:33 PM, Ary Borenszweig wrote:On 6/12/14, 3:04 PM, Nick Sabalausky wrote:No. - It's a negligible amount of extra typing. - I find typing to be the most trivial and least time-consuming aspect of programming. - I rarely need to do that. Most of my "N times" loops exist *because* I want to use the index.On 6/12/2014 11:00 AM, Manu via Digitalmars-d wrote:In Ruby/Crystal you can do: n.times do end In D you have to write: for(unused; 0..n) { } Doesn't it bother you that your language requires more typing and defining dummy variables just for doing something N times?I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile. You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.I can't imagine this has ever been a significant issue for anyone. But that said, I certainly can't disagree with it, and wouldn't object to it.Note, I'm just trying to point out that small improvements in the programmers life will be thanked a lot and more people will join your language.I think you've misunderstood my previous post. I *agree* with Manu. I just don't think it's particularly significant.
Jun 12 2014
On 12/06/14 21:21, Nick Sabalausky wrote:- I rarely need to do that. Most of my "N times" loops exist *because* I want to use the index.I use the "n.times" in Ruby for testing quite a lot. When I need to create x instances of a class and it doesn't matter what values they have. Although I usually use that together with a map. foos = 3.times.map{ Foo.new } -- /Jacob Carlborg
Jun 13 2014
V Thu, 12 Jun 2014 15:33:37 -0300 Ary Borenszweig via Digitalmars-d <digitalmars-d puremagic.com> napsáno:On 6/12/14, 3:04 PM, Nick Sabalausky wrote:No problem for me:On 6/12/2014 11:00 AM, Manu via Digitalmars-d wrote:In Ruby/Crystal you can do: n.times do end In D you have to write: for(unused; 0..n) { } Doesn't it bother you that your language requires more typing and defining dummy variables just for doing something N times? Note, I'm just trying to point out that small improvements in the programmers life will be thanked a lot and more people will join your language.I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile. You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.I can't imagine this has ever been a significant issue for anyone. But that said, I certainly can't disagree with it, and wouldn't object to it.
Jun 12 2014
On Thursday, 12 June 2014 at 22:38:26 UTC, Daniel Kozák via Digitalmars-d wrote:V Thu, 12 Jun 2014 15:33:37 -0300 No problem for me:That is sweet. Well done.
Jun 12 2014
On Thursday, 12 June 2014 at 22:38:26 UTC, Daniel Kozák via Digitalmars-d wrote:No problem for me:Would be nice if we could elide the parentheses and semicolons: 10.times! { writeln("Do It!"); } 10.times! (uint n) { writeln(n + 1, " Round"); }
Jun 13 2014
On 13/06/14 11:28, "Marc Schütz" <schuetzm gmx.net>" wrote:Would be nice if we could elide the parentheses and semicolons: 10.times! { writeln("Do It!"); } 10.times! (uint n) { writeln(n + 1, " Round"); }Yeah, that has been suggested before. -- /Jacob Carlborg
Jun 13 2014
On Thursday, 12 June 2014 at 22:38:26 UTC, Daniel Kozák via Digitalmars-d wrote:No problem for me:Now put a break statement in the loop body.
Jun 13 2014
On 13 June 2014 04:04, Nick Sabalausky via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 6/12/2014 11:00 AM, Manu via Digitalmars-d wrote:It gets awkward when you nest, using '_' leads to '__', and personally, I would expect an 'unreferenced variable' warning for the unused loop counter. I like warnings hassling me about unused variables. I also object to the inconsistency with for(;;). Recall Scott Myers talk... It's theoretically an optimisation too; capturing front may be a costly operation that's not required. Ranges maintain their counters internally, there's no reason to emit code to capture a local copy of 'front' if it's not used. popFront and empty don't imply a byVal copy, they usually just update range counters. I agree, it's trivial, just throwing it out there for opinion.I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile. You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.I can't imagine this has ever been a significant issue for anyone. But that said, I certainly can't disagree with it, and wouldn't object to it.
Jun 12 2014
"Manu via Digitalmars-d" wrote in message news:mailman.2111.1402626404.2907.digitalmars-d puremagic.com...It gets awkward when you nest, using '_' leads to '__',i,j,k,etc work just fine. Are you really nesting your loops that deeply?and personally, I would expect an 'unreferenced variable' warning for the unused loop counter. I like warnings hassling me about unused variables.This is a good point.I also object to the inconsistency with for(;;). Recall Scott Myers talk...Should we also allow "foreach(;)" ? 'for' being so loose is not necessarily something we want to copy.It's theoretically an optimisation too; capturing front may be a costly operation that's not required. Ranges maintain their counters internally, there's no reason to emit code to capture a local copy of 'front' if it's not used. popFront and empty don't imply a byVal copy, they usually just update range counters.The compiler's optimizer will do that just fine.
Jun 12 2014
On Thu, 12 Jun 2014 23:04:08 -0400, Daniel Murphy <yebbliesnospam gmail.com> wrote:"Manu via Digitalmars-d" wrote in messageIn this case, it's being "used" but not by the user. The comparison and increment are done behind the scenes. Note that unused variables typically are on function parameters and are silenced by naming the type but not the variable. This request is not in line with that, it is asking for elimination of the variable and the type, in one special case. If it were to be accepted, I'd push for foreach(x) instead of foreach(;0..x). Cut down all the noise, not just some of it.and personally, I would expect an 'unreferenced variable' warning for the unused loop counter. I like warnings hassling me about unused variables.This is a good point.Completely different. foreach makes no sense without the second statement.I also object to the inconsistency with for(;;). Recall Scott Myers talk...Should we also allow "foreach(;)" ? 'for' being so loose is not necessarily something we want to copy.foreach over a range doesn't make any sense unless you are using the data. This is a non-issue IMO. -SteveIt's theoretically an optimisation too; capturing front may be a costly operation that's not required. Ranges maintain their counters internally, there's no reason to emit code to capture a local copy of 'front' if it's not used. popFront and empty don't imply a byVal copy, they usually just update range counters.The compiler's optimizer will do that just fine.
Jun 12 2014
On 13 June 2014 13:29, Steven Schveighoffer via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Thu, 12 Jun 2014 23:04:08 -0400, Daniel Murphy <yebbliesnospam gmail.com> wrote:The compiler doesn't use the result of front()."Manu via Digitalmars-d" wrote in messageIn this case, it's being "used" but not by the user.and personally, I would expect an 'unreferenced variable' warning for the unused loop counter. I like warnings hassling me about unused variables.This is a good point.The comparison and increment are done behind the scenes.These use popFront() and empty(), not front().Note that unused variables typically are on function parameters and are silenced by naming the type but not the variable. This request is not in line with that, it is asking for elimination of the variable and the type, in one special case.How is it a special case? It would be consistent with for(;;)If it were to be accepted, I'd push for foreach(x) instead of foreach(;0..x). Cut down all the noise, not just some of it.Fine with me. I'd prefer this too.foreach over a range doesn't make any sense unless you are using the data. This is a non-issue IMO.Who says? You can't possibly conceive of a case where the length is the only interesting property? (obviously I'm confronted by the case now, and not for the first time) You'd argue for foreach(_; 0..myRange.length)? That's pretty awkward. Some forward ranges don't have a known length, and can only be summed by an iteration sweep.
Jun 12 2014
On Thu, 12 Jun 2014 23:49:46 -0400, Manu via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 13 June 2014 13:29, Steven Schveighoffer via Digitalmars-d <digitalmars-d puremagic.com> wrote:foreach(x; 0..5) translates to for(auto x = 0; x < 5; ++x) So there is no "front"On Thu, 12 Jun 2014 23:04:08 -0400, Daniel Murphy <yebbliesnospam gmail.com> wrote:The compiler doesn't use the result of front()."Manu via Digitalmars-d" wrote in messageIn this case, it's being "used" but not by the user.and personally, I would expect an 'unreferenced variable' warning for the unused loop counter. I like warnings hassling me about unused variables.This is a good point.I don't understand, 0..n is not a range.The comparison and increment are done behind the scenes.These use popFront() and empty(), not front().foreach(x; 0..5) is a special case of foreach.Note that unused variables typically are on function parameters and are silenced by naming the type but not the variable. This request is not in line with that, it is asking for elimination of the variable and the type, in one special case.How is it a special case? It would be consistent with for(;;)Then use length or walkLengthIf it were to be accepted, I'd push for foreach(x) instead of foreach(;0..x). Cut down all the noise, not just some of it.Fine with me. I'd prefer this too.foreach over a range doesn't make any sense unless you are using the data. This is a non-issue IMO.Who says? You can't possibly conceive of a case where the length is the only interesting property? (obviously I'm confronted by the case now, and not for the first time)You'd argue for foreach(_; 0..myRange.length)? That's pretty awkward.It's how I would do it, but I'd use 'i' instead of '_'Some forward ranges don't have a known length, and can only be summed by an iteration sweep.-Steve
Jun 12 2014
On 13 June 2014 14:14, Steven Schveighoffer via Digitalmars-d <digitalmars-d puremagic.com> wrote:That's inefficient, I might as well perform the iteration while I'm walking. No need for a whole pre-pass. Anyway, you don't need to show me how to work-around the issue. Of you think I'm not capable of figuring out workarounds myself, then I'm rather insulted. The point is, it's crappy, I see no real reason not to support foreach(; range) or foreach(range), it is already precedented by for(;;) (I was initially surprised by inconsistency, I'm sure I'm not alone). I was just throwing it out there as a thought.Some forward ranges don't have a known length, and can only be summed by an iteration sweep.
Jun 12 2014
On Fri, 13 Jun 2014 01:27:24 -0400, Manu via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 13 June 2014 14:14, Steven Schveighoffer via Digitalmars-d <digitalmars-d puremagic.com> wrote:It's the same complexity, O(n). I'm not sure how inefficient it is. Depending on what popFront does, the cache impact may actually make it perform better to do popFront in a tight loop, then do the iterations in a loop later.That's inefficient, I might as well perform the iteration while I'm walking. No need for a whole pre-pass.Some forward ranges don't have a known length, and can only be summed by an iteration sweep.Anyway, you don't need to show me how to work-around the issue. Of you think I'm not capable of figuring out workarounds myself, then I'm rather insulted.Please, don't feel insulted, I was not suggesting you didn't know how to work around the issue. It seemed you weren't aware of what walkLength did.The point is, it's crappy, I see no real reason not to support foreach(; range) or foreach(range), it is already precedented by for(;;) (I was initially surprised by inconsistency, I'm sure I'm not alone). I was just throwing it out there as a thought.I will note that your original request (I thought) was specifically for foreach(;x..y), which is not a D range. I can't think of any useful cases where one wants to iterate over a range and not use the data in the range. The improvement to the language is minimal, but obviously not zero. I just don't think it's worth the benefit to change the syntax. That's all I'm saying. -Steve
Jun 13 2014
On 13 June 2014 13:04, Daniel Murphy via Digitalmars-d <digitalmars-d puremagic.com> wrote:"Manu via Digitalmars-d" wrote in message news:mailman.2111.1402626404.2907.digitalmars-d puremagic.com...Giving explicit names pollutes the local namespace, and the point below about unreferenced variable warnings if you give explicit names.It gets awkward when you nest, using '_' leads to '__',i,j,k,etc work just fine. Are you really nesting your loops that deeply?Well, I don't think it really makes sense in the case of forach, for(;;) loops indefinitely in lieu of a termination condition, foreach(;) would theoretically be a noop. For each thing in nothing would iterate no things zero times; it should probably be an unreachable code warning, given the loop body wouldn't execute.and personally, I would expect an 'unreferenced variable' warning for the unused loop counter. I like warnings hassling me about unused variables.This is a good point.I also object to the inconsistency with for(;;). Recall Scott Myers talk...Should we also allow "foreach(;)" ? 'for' being so loose is not necessarily something we want to copy.Not necessarily. The range might be a lib, and non-pure. The compiler can't optimise/inline/eliminate the call if it doesn't have code. In my experience this is common, I frequently wrap C api's in D-style ranges. Potentially a lot of unnecessary calls to C_API_GetItem(itemIndex).It's theoretically an optimisation too; capturing front may be a costly operation that's not required. Ranges maintain their counters internally, there's no reason to emit code to capture a local copy of 'front' if it's not used. popFront and empty don't imply a byVal copy, they usually just update range counters.The compiler's optimizer will do that just fine.
Jun 12 2014
On Thu, 12 Jun 2014 23:34:27 -0400, Manu via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 13 June 2014 13:04, Daniel Murphy via Digitalmars-d <digitalmars-d puremagic.com> wrote:i, j, k are traditionally loop variables. People have been using them for decades without conflicting their other variables.i,j,k,etc work just fine. Are you really nesting your loops that deeply?Giving explicit names pollutes the local namespace, and the point below about unreferenced variable warnings if you give explicit names.2 options: foreach(i; 0..r.walkLength) { } or while(!r.empty) { r.popFront(); } -SteveThe compiler's optimizer will do that just fine.Not necessarily. The range might be a lib, and non-pure. The compiler can't optimise/inline/eliminate the call if it doesn't have code. In my experience this is common, I frequently wrap C api's in D-style ranges. Potentially a lot of unnecessary calls to C_API_GetItem(itemIndex).
Jun 12 2014
On 13 June 2014 13:42, Steven Schveighoffer via Digitalmars-d <digitalmars-d puremagic.com> wrote:On Thu, 12 Jun 2014 23:34:27 -0400, Manu via Digitalmars-d <digitalmars-d puremagic.com> wrote:walkLength might not be known ahead of time. Lists?On 13 June 2014 13:04, Daniel Murphy via Digitalmars-d <digitalmars-d puremagic.com> wrote:i, j, k are traditionally loop variables. People have been using them for decades without conflicting their other variables.i,j,k,etc work just fine. Are you really nesting your loops that deeply?Giving explicit names pollutes the local namespace, and the point below about unreferenced variable warnings if you give explicit names.2 options: foreach(i; 0..r.walkLength) { }The compiler's optimizer will do that just fine.Not necessarily. The range might be a lib, and non-pure. The compiler can't optimise/inline/eliminate the call if it doesn't have code. In my experience this is common, I frequently wrap C api's in D-style ranges. Potentially a lot of unnecessary calls to C_API_GetItem(itemIndex).or while(!r.empty) { r.popFront(); }This modifies 'r', which foreach doesn't do. I'm forced to capture a copy for the sake of the loop? Sounds like a likely place for bugs to emerge... convert foreach code to this code as an optimisation, and a consecutive loop now terminates immediately changing program behaviour...
Jun 12 2014
On Thu, 12 Jun 2014 23:55:20 -0400, Manu via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 13 June 2014 13:42, Steven Schveighoffer via Digitalmars-d <digitalmars-d puremagic.com> wrote:walkLength is for ranges you don't know the length ahead of time. It executes the popFront/empty routines until exhaustion, returning the number of times popFront was required. And it should be trivial to create a wrapper that does not access front, but instead generates an index.On Thu, 12 Jun 2014 23:34:27 -0400, Manu via Digitalmars-d <digitalmars-d puremagic.com> wrote:walkLength might not be known ahead of time. Lists?On 13 June 2014 13:04, Daniel Murphy via Digitalmars-d <digitalmars-d puremagic.com> wrote:i, j, k are traditionally loop variables. People have been using them for decades without conflicting their other variables.i,j,k,etc work just fine. Are you really nesting your loops that deeply?Giving explicit names pollutes the local namespace, and the point below about unreferenced variable warnings if you give explicit names.2 options: foreach(i; 0..r.walkLength) { }The compiler's optimizer will do that just fine.Not necessarily. The range might be a lib, and non-pure. The compiler can't optimise/inline/eliminate the call if it doesn't have code. In my experience this is common, I frequently wrap C api's in D-style ranges. Potentially a lot of unnecessary calls to C_API_GetItem(itemIndex).Then use the first option. -Steveor while(!r.empty) { r.popFront(); }This modifies 'r', which foreach doesn't do. I'm forced to capture a copy for the sake of the loop? Sounds like a likely place for bugs to emerge... convert foreach code to this code as an optimisation, and a consecutive loop now terminates immediately changing program behaviour...
Jun 12 2014
On Fri, 13 Jun 2014 12:26:34 +1000 Manu via Digitalmars-d <digitalmars-d puremagic.com> wrote:It gets awkward when you nest, using '_' leads to '__', and personally, I would expect an 'unreferenced variable' warning for the unused loop counter. I like warnings hassling me about unused variables.I don't expect that to ever happen in D. There are too many places where variables are unused on purpose - especially in code used for template constraints (e.g. isInputRange has an unused variable in it). Having warnings about unused variables could then not only be counter-productive, but when combined with -w, they could easily break a lot of code.I also object to the inconsistency with for(;;). Recall Scott Myers talk...Personally, I don't think that that should even be legal. while(1) works just as well without requiring any special cases.It's theoretically an optimisation too; capturing front may be a costly operation that's not required. Ranges maintain their counters internally, there's no reason to emit code to capture a local copy of 'front' if it's not used. popFront and empty don't imply a byVal copy, they usually just update range counters.That's an interesting idea. However, I would expect it to be a rare benefit, particularly when the primary use case is with integers. - Jonathan M Davis
Jun 12 2014
On Thursday, 12 June 2014 at 15:00:20 UTC, Manu via Digitalmars-d wrote:I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile. You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.Seems like a nice idea. Especially useful when it comes to reading other people's code: foreach (i; 0..n) { some(); long(); list(); of(); tasks(); } // I always double back--"wait, where did they use `i`?"
Jun 12 2014
On 12/06/14 17:00, Manu via Digitalmars-d wrote:I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile. You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.The only reason I can see to make this change is to make it more consistent with "for". But I don't know if it's "for" that is inconsistent with everything else or if it's "foreach" that is inconsistent with "for". -- /Jacob Carlborg
Jun 13 2014
On Thursday, 12 June 2014 at 15:00:20 UTC, Manu via Digitalmars-d wrote:I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile. You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.Over 50 comments about minor syntax issue that makes no practical difference. D community never changes :P
Jun 13 2014
On 06/13/2014 01:55 PM, Dicebot wrote:Over 50 comments about minor syntax issue ...Including yours.
Jun 13 2014
On Friday, 13 June 2014 at 15:48:37 UTC, Timon Gehr wrote:On 06/13/2014 01:55 PM, Dicebot wrote:That was my first comment in this thread :OOver 50 comments about minor syntax issue ...Including yours.
Jun 13 2014
On 13/06/2014 3:00 a.m., Manu via Digitalmars-d wrote:I often find myself wanting to write this: foreach(; 0..n) {} In the case that I just want to do something n times and I don't actually care about the loop counter, but this doesn't compile. You can do this: for(;;) {} If 'for' lets you omit any of the loop terms, surely it makes sense that foreach would allow you to omit the first term as well? I see no need to declare a superfluous loop counter when it is unused.Of course my reaction is a library solution: import std.stdio; import std.traits; void times(size_t n, void delegate() c) { for (size_t i = 0; i < n; i++) c(); } void times(size_t n, void delegate(size_t) c) { for (size_t i = 0; i < n; i++) c(i); } void iterate(T, U = typeof((T.init)[0]))(T t, void delegate(U) c) { foreach(v; t) c(v); } void iterate(T, U = typeof((T.init)[0]))(T t, void delegate(U, size_t) c) { foreach(i, v; t) c(v, i); } void main() { 4.times({ writeln("hi"); }); 4.times((i) { writeln("hello ", i); }); [1, 2, 3].iterate((uint c) { writeln("letter: ", c); }); [1, 2, 3].iterate((uint c, i) { writeln("letter: ", c, ", at: ", i); }); } But not really what you're wanting I'd imagine.
Jun 13 2014
The idea of using code like this (only one or the other should be allowed) is rather natural, it breaks nothing, it avoids the programmer to introduce a variable that is not needed, making the code less noisy: foreach (;0 .. 10) {...} foreach (0 .. 10) {...} I don't see the need for so many posts against this simple and innocous idea that's a small improvement. Improvements don't need to be large to be good, if their price is correspondingly small (as in this case). (With an attitude like the current one no small positive feature like the "_" to separate digits in numbers literals could have seen the light). With a little breaking change "_" could become a name that can't be referenced, so you can also do: foreach (_; 0 .. 10) { // OK foreach (_; 0 .. 20) { // OK writeln(_); // syntax error } } Or: foreach (immutable i, _; items) {...} The _ can also be used as "don't care" for tuple unpacking, this is a very important usage: t{_, b} = fooAB(); And in switch on structs (that contain the optional "unapply" method): switch (foo) { case Foo(x, _, _): writeln(x); break; default: } An alternative idea is to use "__", that is a reserved identifier. It's a little longer but I think it's still acceptable: foreach (__; 0 .. 10) { // OK foreach (__; 0 .. 20) { // OK writeln(__); // syntax error } } foreach (immutable i, __; items) {...} t{__, b} = fooAB(); switch (foo) { case Foo(x, __, __): writeln(x); break; default: } Bye, bearophile
Jun 14 2014