www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - foreach

reply Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
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
next sibling parent "Meta" <jared771 gmail.com> writes:
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
prev sibling next sibling parent reply simendsjo <simendsjo gmail.com> writes:
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
parent reply simendsjo <simendsjo gmail.com> writes:
On 06/12/2014 05:46 PM, monarch_dodra wrote:
 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.

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 :)
Jun 12 2014
next sibling parent reply Nick Treleaven <ntrel-public yahoo.co.uk> writes:
On 12/06/2014 16:57, simendsjo wrote:
 On 06/12/2014 05:46 PM, monarch_dodra wrote:
 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.

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.

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 element
 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
next sibling parent reply Nick Treleaven <ntrel-public yahoo.co.uk> writes:
On 12/06/2014 17:59, bearophile wrote:
 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.

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)
Jun 12 2014
parent Nick Treleaven <ntrel-public yahoo.co.uk> writes:
On 12/06/2014 18:30, Nick Treleaven wrote:
 On 12/06/2014 17:59, bearophile wrote:
 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.

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)

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).
Jun 14 2014
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06/12/2014 06:59 PM, bearophile wrote:
 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.

Have you ever used void[0][T]?
Jun 13 2014
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 06/14/2014 05:33 PM, bearophile wrote:
 Timon Gehr:

 Have you ever used void[0][T]?

I have never used that so far. What is it useful for? Bye, bearophile

It's a hash set with a somewhat awkward interface.
Jun 14 2014
prev sibling parent Nick Treleaven <ntrel-public yahoo.co.uk> writes:
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
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 12 June 2014 at 15:14:44 UTC, bearophile wrote:
 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

Enhancement request filed last year: https://issues.dlang.org/show_bug.cgi?id=9009
Jun 12 2014
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
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
prev sibling next sibling parent "Rene Zwanenburg" <renezwanenburg gmail.com> writes:
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
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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 element

This is a very important usage. Worthing breaking D2 on. Bye, bearophile
Jun 12 2014
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
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:

 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.

The compiler needs a variable. The programmer doesn't.
Jun 12 2014
parent reply Andrew Edwards <ridimz yahoo.com> writes:
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:

 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:

 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.

The compiler needs a variable. The programmer doesn't.

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. -Steve

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.
Jun 12 2014
parent reply Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> writes:
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.
 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.

FWIW: I think this can be viewed more as "Lifting undue restrictions".
Jun 12 2014
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 06/12/2014 10:06 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. -Steve

Why would implicit local variables need unique names? This can be implemented by preventing identifiers named '_' to be inserted into the symbol table.
Jun 12 2014
prev sibling next sibling parent Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> writes:
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:
 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.

Well, s/triviality/limited importance/ Slightly inaccurate word choice, whatever ;)
Jun 12 2014
prev sibling next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
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:

 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.

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

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.
Jun 12 2014
parent reply Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> writes:
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
parent Ary Borenszweig <ary esperanto.org.ar> writes:
On 6/12/14, 9:41 PM, Nick Sabalausky wrote:
 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?

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.
Jun 13 2014
prev sibling parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"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
prev sibling next sibling parent "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
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:
 
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.

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. }; --T
Jun 12 2014
prev sibling next sibling parent "Demetri" <Supernova2003dh yahoo.com> writes:
On Thursday, 12 June 2014 at 15:56:17 UTC, simendsjo wrote:
 On 06/12/2014 05:46 PM, monarch_dodra wrote:
 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.

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 :)

Those are already reserved.
Jun 12 2014
prev sibling next sibling parent reply Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> writes:
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
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
On 6/12/14, 3:04 PM, Nick Sabalausky wrote:
 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.

In Ruby/Crystal you can do: n.times do # code end In D you have to write: for(unused; 0..n) { # code } 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.
Jun 12 2014
next sibling parent reply Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> writes:
On 6/12/2014 2:33 PM, Ary Borenszweig wrote:
 On 6/12/14, 3:04 PM, Nick Sabalausky wrote:
 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.

In Ruby/Crystal you can do: n.times do # code end In D you have to write: for(unused; 0..n) { # code } Doesn't it bother you that your language requires more typing and defining dummy variables just for doing something N times?

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.
 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
parent Jacob Carlborg <doob me.com> writes:
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
prev sibling parent Jacob Carlborg <doob me.com> writes:
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
prev sibling parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"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
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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:
 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.

The compiler needs a variable. The programmer doesn't.

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. -Steve
Jun 12 2014
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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:
 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:
 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.

The compiler needs a variable. The programmer doesn't.

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. -Steve

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.

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(;...
 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
prev sibling next sibling parent "Sebastiaan Koppe" <mail skoppe.eu> writes:
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
   # code
 end

 In D you have to write:

 for(unused; 0..n) {
   # code
 }

 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
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
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
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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:
 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.

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
prev sibling next sibling parent "Mason McGill" <mmcgill caltech.edu> writes:
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
prev sibling next sibling parent Daniel =?UTF-8?B?S296w6Fr?= via Digitalmars-d writes:
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:
 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.

In Ruby/Crystal you can do: n.times do # code end In D you have to write: for(unused; 0..n) { # code } 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.

No problem for me: http://stackoverflow.com/questions/23950796/how-to-repeat-a-statement-n-times-simple-loop/23952012#23952012
Jun 12 2014
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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:

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

Why would implicit local variables need unique names? This can be implemented by preventing identifiers named '_' to be inserted into the symbol table.

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. -Steve
Jun 12 2014
prev sibling next sibling parent "Craig Dillabaugh" <craig.dillabaugh gmail.com> writes:
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:
 http://stackoverflow.com/questions/23950796/how-to-repeat-a-statement-n-times-simple-loop/23952012#23952012

That is sweet. Well done.
Jun 12 2014
prev sibling next sibling parent Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
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:
 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.

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.
Jun 12 2014
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 12 Jun 2014 23:04:08 -0400, Daniel Murphy  
<yebbliesnospam gmail.com> wrote:

 "Manu via Digitalmars-d"  wrote in message
 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.

In 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.
 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.

Completely different. foreach makes no sense without the second statement.
 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.

foreach over a range doesn't make any sense unless you are using the data. This is a non-issue IMO. -Steve
Jun 12 2014
prev sibling next sibling parent Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
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...


 It gets awkward when you nest, using '_' leads to '__',

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.
 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.

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.
 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.

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
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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,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.

i, j, k are traditionally loop variables. People have been using them for decades without conflicting their other variables.
 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).

2 options: foreach(i; 0..r.walkLength) { } or while(!r.empty) { r.popFront(); } -Steve
Jun 12 2014
prev sibling next sibling parent Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
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
prev sibling next sibling parent Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
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:

 "Manu via Digitalmars-d"  wrote in message
 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.

In this case, it's being "used" but not by the user.

The compiler doesn't use the result of front().
 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
prev sibling next sibling parent Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
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:

 On 13 June 2014 13:04, Daniel Murphy via Digitalmars-d
 <digitalmars-d puremagic.com> wrote:
 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.

i, j, k are traditionally loop variables. People have been using them for decades without conflicting their other variables.
 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).

2 options: foreach(i; 0..r.walkLength) { }

walkLength might not be known ahead of time. Lists?
 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
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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:
 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,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.

i, j, k are traditionally loop variables. People have been using them for decades without conflicting their other variables.
 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).

2 options: foreach(i; 0..r.walkLength) { }

walkLength might not be known ahead of time. Lists?

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.
 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...

Then use the first option. -Steve
Jun 12 2014
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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:
 On Thu, 12 Jun 2014 23:04:08 -0400, Daniel Murphy  
 <yebbliesnospam gmail.com>
 wrote:

 "Manu via Digitalmars-d"  wrote in message
 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.

In this case, it's being "used" but not by the user.

The compiler doesn't use the result of front().

foreach(x; 0..5) translates to for(auto x = 0; x < 5; ++x) So there is no "front"
 The comparison and increment are done behind the scenes.

These use popFront() and empty(), not front().

I don't understand, 0..n is not a range.
 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(;;)

foreach(x; 0..5) is a special case of foreach.
 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)

Then use length or walkLength
 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.

http://dlang.org/phobos/std_range.html#.walkLength -Steve
Jun 12 2014
prev sibling next sibling parent Manu via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 13 June 2014 14:14, Steven Schveighoffer via Digitalmars-d
<digitalmars-d puremagic.com> wrote:

 Some forward ranges don't have a known length, and can only be summed
 by an iteration sweep.

http://dlang.org/phobos/std_range.html#.walkLength

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.
Jun 12 2014
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
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
prev sibling next sibling parent "JR" <zorael gmail.com> writes:
On Thursday, 12 June 2014 at 16:59:34 UTC, bearophile wrote:
 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.

Would enforcing immutability there be a breaking change? foreach (/*immutable*/ i; _; range) { version(none) i = 0; }
Jun 13 2014
prev sibling next sibling parent "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Thursday, 12 June 2014 at 22:38:26 UTC, Daniel Kozák via 
Digitalmars-d wrote:
 No problem for me:
 http://stackoverflow.com/questions/23950796/how-to-repeat-a-statement-n-times-simple-loop/23952012#23952012

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
prev sibling next sibling parent reply "Dicebot" <public dicebot.lv> writes:
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
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 06/13/2014 01:55 PM, Dicebot wrote:
 Over 50 comments about minor syntax issue ...

Including yours.
Jun 13 2014
prev sibling next sibling parent Rikki Cattermole <alphaglosined gmail.com> writes:
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
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 13 June 2014 at 15:18:52 UTC, Nick Treleaven wrote:
 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!"));

C++ also recently defined some std::placeholders, which are _1, _2 through _N.
Jun 13 2014
prev sibling next sibling parent "Sean Kelly" <sean invisibleduck.org> writes:
On Thursday, 12 June 2014 at 22:38:26 UTC, Daniel Kozák via 
Digitalmars-d wrote:
 No problem for me:
 http://stackoverflow.com/questions/23950796/how-to-repeat-a-statement-n-times-simple-loop/23952012#23952012

Now put a break statement in the loop body.
Jun 13 2014
prev sibling next sibling parent "Dicebot" <public dicebot.lv> writes:
On Friday, 13 June 2014 at 15:48:37 UTC, Timon Gehr wrote:
 On 06/13/2014 01:55 PM, Dicebot wrote:
 Over 50 comments about minor syntax issue ...

Including yours.

That was my first comment in this thread :O
Jun 13 2014
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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:

 Some forward ranges don't have a known length, and can only be summed
 by an iteration sweep.

http://dlang.org/phobos/std_range.html#.walkLength

That's inefficient, I might as well perform the iteration while I'm walking. No need for a whole pre-pass.

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.
 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
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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