digitalmars.D - suggested change to foreach index
- BCS (30/30) Jun 07 2006 I often find my self doing something like this:
- Ameer Armaly (3/33) Jun 07 2006 Wouldn't a function return serve a similar if not identical purpose?
- Regan Heath (21/63) Jun 07 2006 Requiring you to put the foreach in a function? Probably.
- Ameer Armaly (5/68) Jun 07 2006 It just seems to me that if you want something to loop over a set and in...
- BCS (6/48) Jun 07 2006 Yes, but that would require putting the foreach in a function. If it nee...
- Derek Parnell (18/56) Jun 07 2006 I see what you mean but have you tried this ...
- BCS (15/42) Jun 07 2006 That would work but its not vary expandable. Try doing that for five or ...
- Sean Kelly (24/24) Jun 07 2006 What's weird to me is if I do this:
- Deewiant (10/42) Jun 08 2006 It creates a new scope, just like for loops:
- Sean Kelly (10/50) Jun 08 2006 Yes, but my example was equivalent to this (I thought):
- Deewiant (7/41) Jun 08 2006 I guess it's the type inference that makes it so confusing to some. Earl...
- BCS (7/57) Jun 08 2006 The suggested syntax
- Jarrett Billingsley (12/18) Jun 08 2006 Or, more consistent, make auto foreach indices require "auto"?
- Tom S (4/19) Jun 08 2006 ++votes; // fully agreed
- Derek Parnell (7/8) Jun 08 2006 This will break some existing code but I think its worth it. It's a good...
- Sean Kelly (3/30) Jun 08 2006 I was thinking the same thing. Definitely has my vote.
- Bruno Medeiros (6/35) Jun 10 2006 Agreed too, this is the natural/intuitive/consistent way to go.
- Deewiant (10/32) Jun 10 2006 I guess I'm the only one that doesn't like this idea, then. I think "aut...
- BCS (18/45) Jun 10 2006 Come to think of it, that would be consistent, the variable never caries...
- Jarrett Billingsley (15/30) Jun 10 2006 I'd really like something else for type inference too, but until that
I often find my self doing something like this: <code> int i char[] arr; foreach(int j, c; arr) if(' ' == c) { i=j; // copy j out of foreach's scope break; } if(i < arr.length) { arr = arr.dup; // use copy of j foreach(inout c; arr[i..$]) if(' ' == c) c = '_'; } </code> In this case it would be nice to be able to use a variable in the outer scope as the index in the foreach, e.i. <code> int i char[] arr; foreach(int i, c; arr) if(' ' == c) break; // i keeps the value from the last time through ... </code> Thoughts comments??
Jun 07 2006
"BCS" <BCS pathlink.com> wrote in message news:e67p90$rol$1 digitaldaemon.com...I often find my self doing something like this: <code> int i char[] arr; foreach(int j, c; arr) if(' ' == c) { i=j; // copy j out of foreach's scope break; } if(i < arr.length) { arr = arr.dup; // use copy of j foreach(inout c; arr[i..$]) if(' ' == c) c = '_'; } </code> In this case it would be nice to be able to use a variable in the outer scope as the index in the foreach, e.i. <code> int i char[] arr; foreach(int i, c; arr) if(' ' == c) break; // i keeps the value from the last time through ... </code> Thoughts comments??Wouldn't a function return serve a similar if not identical purpose?
Jun 07 2006
On Wed, 7 Jun 2006 20:27:51 -0400, Ameer Armaly <ameer_armaly hotmail.com> wrote:"BCS" <BCS pathlink.com> wrote in message news:e67p90$rol$1 digitaldaemon.com...Requiring you to put the foreach in a function? Probably. At the very least we need some way to indicate we want the behaviour as it really shouldn't use variables external to the foreach by default. eg. int i; char[] arr; foreach(inout int i, c; arr) {} or foreach(inout i, c; arr) {} or something. Something/anything to indicate the 'i' in the loop is the 'i' from outside the loop. Or, perhaps another block which is executed with the foreach variables when the loop doesn't terminate normally: foreach(int i, c; arr) { } else { //comes here if you use 'break' in foreach //i, and c have the last values they had in the loop. //what happens in the 'inout c' cases? } ReganI often find my self doing something like this: <code> int i char[] arr; foreach(int j, c; arr) if(' ' == c) { i=j; // copy j out of foreach's scope break; } if(i < arr.length) { arr = arr.dup; // use copy of j foreach(inout c; arr[i..$]) if(' ' == c) c = '_'; } </code> In this case it would be nice to be able to use a variable in the outer scope as the index in the foreach, e.i. <code> int i char[] arr; foreach(int i, c; arr) if(' ' == c) break; // i keeps the value from the last time through ... </code> Thoughts comments??Wouldn't a function return serve a similar if not identical purpose?
Jun 07 2006
"Regan Heath" <regan netwin.co.nz> wrote in message news:optasxzhwe23k2f5 nrage.netwin.co.nz...On Wed, 7 Jun 2006 20:27:51 -0400, Ameer Armaly <ameer_armaly hotmail.com> wrote:It just seems to me that if you want something to loop over a set and inform you of the stopping point, that's the natural place for a function, though I could be overlooking some corner cases."BCS" <BCS pathlink.com> wrote in message news:e67p90$rol$1 digitaldaemon.com...Requiring you to put the foreach in a function? Probably.I often find my self doing something like this: <code> int i char[] arr; foreach(int j, c; arr) if(' ' == c) { i=j; // copy j out of foreach's scope break; } if(i < arr.length) { arr = arr.dup; // use copy of j foreach(inout c; arr[i..$]) if(' ' == c) c = '_'; } </code> In this case it would be nice to be able to use a variable in the outer scope as the index in the foreach, e.i. <code> int i char[] arr; foreach(int i, c; arr) if(' ' == c) break; // i keeps the value from the last time through ... </code> Thoughts comments??Wouldn't a function return serve a similar if not identical purpose?At the very least we need some way to indicate we want the behaviour as it really shouldn't use variables external to the foreach by default. eg. int i; char[] arr; foreach(inout int i, c; arr) {} or foreach(inout i, c; arr) {} or something. Something/anything to indicate the 'i' in the loop is the 'i' from outside the loop. Or, perhaps another block which is executed with the foreach variables when the loop doesn't terminate normally: foreach(int i, c; arr) { } else { //comes here if you use 'break' in foreach //i, and c have the last values they had in the loop. //what happens in the 'inout c' cases? } Regan
Jun 07 2006
In article <e67qth$ugk$1 digitaldaemon.com>, Ameer Armaly says..."BCS" <BCS pathlink.com> wrote in message news:e67p90$rol$1 digitaldaemon.com...Yes, but that would require putting the foreach in a function. If it needs to access local variables then it needs to be a nested function and therefore could results in a lot of lookup by pointer. Also there is the added function call overhead associated with it. If the code is performance critical all of these are bad things.I often find my self doing something like this: <code> int i char[] arr; foreach(int j, c; arr) if(' ' == c) { i=j; // copy j out of foreach's scope break; } if(i < arr.length) { arr = arr.dup; // use copy of j foreach(inout c; arr[i..$]) if(' ' == c) c = '_'; } </code> In this case it would be nice to be able to use a variable in the outer scope as the index in the foreach, e.i. <code> int i char[] arr; foreach(int i, c; arr) if(' ' == c) break; // i keeps the value from the last time through ... </code> Thoughts comments??Wouldn't a function return serve a similar if not identical purpose?
Jun 07 2006
On Wed, 07 Jun 2006 17:04:09 -0700, BCS wrote:I often find my self doing something like this: <code> int i char[] arr; foreach(int j, c; arr) if(' ' == c) { i=j; // copy j out of foreach's scope break; } if(i < arr.length) { arr = arr.dup; // use copy of j foreach(inout c; arr[i..$]) if(' ' == c) c = '_'; } </code> In this case it would be nice to be able to use a variable in the outer scope as the index in the foreach, e.i. <code> int i char[] arr; foreach(int i, c; arr) if(' ' == c) break; // i keeps the value from the last time through ... </code> Thoughts comments??I see what you mean but have you tried this ... int i; char[] arr; foreach(int j, c; arr) if(' ' == c) { arr = arr.dup; foreach(inout c; arr[j..$]) if(' ' == c) c = '_'; break; } -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocracy!" 8/06/2006 11:12:32 AM
Jun 07 2006
In article <cs4o03emrdkm$.b5qasiolumf7.dlg 40tude.net>, Derek Parnell says...On Wed, 07 Jun 2006 17:04:09 -0700, BCS wrote:[...]I often find my self doing something like this:That would work but its not vary expandable. Try doing that for five or six loops. The proposed solution is just a lot cleaner, even in the two loop case. Or how about doing that with something like: char[] arr; int j=0, i, skip; do { foreach(inout i, c; arr[j..$]) if(‘ ' == c) break; // do something and continue j+=(i+skip); }while(i != arr.length)<code> int i char[] arr; foreach(int i, c; arr) if(' ' == c) break; // i keeps the value from the last time through ... </code> Thoughts comments??I see what you mean but have you tried this ... int i; char[] arr; foreach(int j, c; arr) if(' ' == c) { arr = arr.dup; foreach(inout c; arr[j..$]) if(' ' == c) c = '_'; break; }
Jun 07 2006
What's weird to me is if I do this: void main() { int i; char[] arr = "abc def"; foreach( i, c; arr ) { printf( "%i\n", i ); if(' ' == c) break; } printf( "\n%i\n", i ); } Then the output is: 0 1 2 3 0 So the code compiles without a type for i in the foreach, but rather than use the instance of i in the surrounding scope a local value is used instead. The spec isn't clear on what should happen here, but I would have guessed that the final value displayed would be 3, not 0. Sean
Jun 07 2006
Sean Kelly wrote:What's weird to me is if I do this: void main() { int i; char[] arr = "abc def"; foreach( i, c; arr ) { printf( "%i\n", i ); if(' ' == c) break; } printf( "\n%i\n", i ); } Then the output is: 0 1 2 3 0 So the code compiles without a type for i in the foreach, but rather than use the instance of i in the surrounding scope a local value is used instead. The spec isn't clear on what should happen here, but I would have guessed that the final value displayed would be 3, not 0. SeanIt creates a new scope, just like for loops: int i = 5; for (int i = 0; i < 3; ++i) writefln(i); // 0 to 2 writefln(i); // 5 I don't know about the spec's opinion, but this is how it has always worked, both with for and foreach, and I have a lot of code that relies on this behaviour. The "inout" suggested elsewhere in the thread by Regan Heath seems like a good solution to me.
Jun 08 2006
Deewiant wrote:Sean Kelly wrote:Yes, but my example was equivalent to this (I thought): int i = 5; for (i = 0; i < 3; ++i) writefln(i); // 0 to 2 writefln(i); // 2 ie, the lack of a type makes the "i=0" an assignment, not a declaration with an initializer. The i from the surrounding scope is used. I expected foreach to behave the same way, but apparently it doesn't. SeanWhat's weird to me is if I do this: void main() { int i; char[] arr = "abc def"; foreach( i, c; arr ) { printf( "%i\n", i ); if(' ' == c) break; } printf( "\n%i\n", i ); } Then the output is: 0 1 2 3 0 So the code compiles without a type for i in the foreach, but rather than use the instance of i in the surrounding scope a local value is used instead. The spec isn't clear on what should happen here, but I would have guessed that the final value displayed would be 3, not 0. SeanIt creates a new scope, just like for loops: int i = 5; for (int i = 0; i < 3; ++i) writefln(i); // 0 to 2 writefln(i); // 5
Jun 08 2006
Sean Kelly wrote:Deewiant wrote:I guess it's the type inference that makes it so confusing to some. Earlier, after all, we had to write: foreach (int i, char[] c; arr) Instead of the modern terse version: foreach (i, c; arr) In the longer version, it's presumably more clear that the i is a new "int i".Sean Kelly wrote:Yes, but my example was equivalent to this (I thought): int i = 5; for (i = 0; i < 3; ++i) writefln(i); // 0 to 2 writefln(i); // 2 ie, the lack of a type makes the "i=0" an assignment, not a declaration with an initializer. The i from the surrounding scope is used. I expected foreach to behave the same way, but apparently it doesn't.void main() { int i; char[] arr = "abc def"; foreach( i, c; arr ) { printf( "%i\n", i ); if(' ' == c) break; } printf( "\n%i\n", i ); }It creates a new scope, just like for loops: int i = 5; for (int i = 0; i < 3; ++i) writefln(i); // 0 to 2 writefln(i); // 5
Jun 08 2006
Deewiant wrote:Sean Kelly wrote:The suggested syntax vvv foreach([[inout] index,] value ; ... seems a bit odd to me. How about use "alias" instead? int i; foreach(alias i, v; arr){}Deewiant wrote:I guess it's the type inference that makes it so confusing to some. Earlier, after all, we had to write: foreach (int i, char[] c; arr) Instead of the modern terse version: foreach (i, c; arr) In the longer version, it's presumably more clear that the i is a new "int i".Sean Kelly wrote:Yes, but my example was equivalent to this (I thought): int i = 5; for (i = 0; i < 3; ++i) writefln(i); // 0 to 2 writefln(i); // 2 ie, the lack of a type makes the "i=0" an assignment, not a declaration with an initializer. The i from the surrounding scope is used. I expected foreach to behave the same way, but apparently it doesn't.void main() { int i; char[] arr = "abc def"; foreach( i, c; arr ) { printf( "%i\n", i ); if(' ' == c) break; } printf( "\n%i\n", i ); }It creates a new scope, just like for loops: int i = 5; for (int i = 0; i < 3; ++i) writefln(i); // 0 to 2 writefln(i); // 5
Jun 08 2006
"BCS" <BCS pathlink.com> wrote in message news:e69lah$dmo$1 digitaldaemon.com...The suggested syntax vvv foreach([[inout] index,] value ; ... seems a bit odd to me. How about use "alias" instead? int i; foreach(alias i, v; arr){}Or, more consistent, make auto foreach indices require "auto"? int i; foreach(auto i, auto j; something) writefln(i); // New local i which overrides outer i foreach(i, auto j; something) writefln(i); // Uses outer i writefln(i); // Writes the value that i last had in the loop This has the (wonderful) side-effect of making it bleedingly obvious that the foreach indices are using type inference; the current index inference form _looks_ like it's trying to use already-defined index variables.
Jun 08 2006
Jarrett Billingsley wrote:Or, more consistent, make auto foreach indices require "auto"? int i; foreach(auto i, auto j; something) writefln(i); // New local i which overrides outer i foreach(i, auto j; something) writefln(i); // Uses outer i writefln(i); // Writes the value that i last had in the loop This has the (wonderful) side-effect of making it bleedingly obvious that the foreach indices are using type inference; the current index inference form _looks_ like it's trying to use already-defined index variables.++votes; // fully agreed -- Tomasz Stachowiak /+ a.k.a. h3r3tic +/
Jun 08 2006
On Fri, 09 Jun 2006 06:49:11 +1000, Jarrett Billingsley <kb3ctd2 yahoo.com> wrote:Or, more consistent, make auto foreach indices require "auto"?This will break some existing code but I think its worth it. It's a good idea. -- Derek Parnell Melbourne, Australia
Jun 08 2006
Jarrett Billingsley wrote:"BCS" <BCS pathlink.com> wrote in message news:e69lah$dmo$1 digitaldaemon.com...I was thinking the same thing. Definitely has my vote. SeanThe suggested syntax vvv foreach([[inout] index,] value ; ... seems a bit odd to me. How about use "alias" instead? int i; foreach(alias i, v; arr){}Or, more consistent, make auto foreach indices require "auto"? int i; foreach(auto i, auto j; something) writefln(i); // New local i which overrides outer i foreach(i, auto j; something) writefln(i); // Uses outer i writefln(i); // Writes the value that i last had in the loop This has the (wonderful) side-effect of making it bleedingly obvious that the foreach indices are using type inference; the current index inference form _looks_ like it's trying to use already-defined index variables.
Jun 08 2006
Jarrett Billingsley wrote:"BCS" <BCS pathlink.com> wrote in message news:e69lah$dmo$1 digitaldaemon.com...Agreed too, this is the natural/intuitive/consistent way to go. Those other solutions with "alias" and "inout" were awful. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DThe suggested syntax vvv foreach([[inout] index,] value ; ... seems a bit odd to me. How about use "alias" instead? int i; foreach(alias i, v; arr){}Or, more consistent, make auto foreach indices require "auto"? int i; foreach(auto i, auto j; something) writefln(i); // New local i which overrides outer i foreach(i, auto j; something) writefln(i); // Uses outer i writefln(i); // Writes the value that i last had in the loop This has the (wonderful) side-effect of making it bleedingly obvious that the foreach indices are using type inference; the current index inference form _looks_ like it's trying to use already-defined index variables.
Jun 10 2006
Bruno Medeiros wrote:Jarrett Billingsley wrote:I guess I'm the only one that doesn't like this idea, then. I think "auto" is overloaded enough as it is; I'm still waiting for "var" or some such for type inference. And I always thought it was obvious that foreach() uses its own index, but that might be since I've only recently (say, a few days back) begun to use type inference with it. When you write "size_t i, type x; something" it's obvious enough, and when I write "i, type x" I think of the longer form, realising it's short for just that. Personally, I'd prefer "out" instead of "inout" or "alias", but that's just me. <g>Or, more consistent, make auto foreach indices require "auto"? int i; foreach(auto i, auto j; something) writefln(i); // New local i which overrides outer i foreach(i, auto j; something) writefln(i); // Uses outer i writefln(i); // Writes the value that i last had in the loop This has the (wonderful) side-effect of making it bleedingly obvious that the foreach indices are using type inference; the current index inference form _looks_ like it's trying to use already-defined index variables.Agreed too, this is the natural/intuitive/consistent way to go. Those other solutions with "alias" and "inout" were awful.
Jun 10 2006
In article <e6ev28$o1k$1 digitaldaemon.com>, Deewiant says...Yup, a type inference keyword would be nice.Jarrett Billingsley wrote:I guess I'm the only one that doesn't like this idea, then. I think "auto" is overloaded enough as it is; I'm still waiting for "var" or some such for type inference.Or, more consistent, make auto foreach indices require "auto"? int i; foreach(auto i, auto j; something) writefln(i); // New local i which overrides outer i foreach(i, auto j; something) writefln(i); // Uses outer i writefln(i); // Writes the value that i last had in the loop This has the (wonderful) side-effect of making it bleedingly obvious that the foreach indices are using type inference; the current index inference form _looks_ like it's trying to use already-defined index variables.And I always thought it was obvious that foreach() uses its own index, but that might be since I've only recently (say, a few days back) begun to use type inference with it. When you write "size_t i, type x; something" it's obvious enough, and when I write "i, type x" I think of the longer form, realising it's short for just that. Personally, I'd prefer "out" instead of "inout" or "alias", but that's just me. <g>Come to think of it, that would be consistent, the variable never caries in a value at the start of the loop. Also it sounds nice: " this variable is outside this scope" On a different track: given this <code> int i; foreach(out i, char c; "ab"){i=3} writef(i,\n); </code> what is printed? 1, 2 or 3? It is 1 if i exits with the last value the loop sets it to. It is 2 if i exits with the first value that doesn't match It is 3 if i keeps its value at the point the loop is exited. I would go with 1 or maybe 3. 2 becomes undefined with an AA Thoughts? Comments?
Jun 10 2006
"Deewiant" <deewiant.doesnotlike.spam gmail.com> wrote in message news:e6ev28$o1k$1 digitaldaemon.com...I guess I'm the only one that doesn't like this idea, then. I think "auto" is overloaded enough as it is; I'm still waiting for "var" or some such for type inference.I'd really like something else for type inference too, but until that happens, "auto" would make the most sense. I think 'var' or something along those lines would be better; and it would be best if it functioned _as a type_ which would just stand for a "placeholder" type until the type could be determined in the semantic pass.And I always thought it was obvious that foreach() uses its own index, but that might be since I've only recently (say, a few days back) begun to use type inference with it. When you write "size_t i, type x; something" it's obvious enough, and when I write "i, type x" I think of the longer form, realising it's short for just that.Well, keep in mind that many of my proposals are based on my virulent hatred of most uses of type inference ;) It's bad enough when people start overusing auto; it's worse when it's not even obvious that a new variable is being declared as well!Personally, I'd prefer "out" instead of "inout" or "alias", but that's just me. <g>That's good too, but the best would be if/when we get a true type-inference keyword for use with index inference, and then nothing when you want to use the outer scope's variable (to be consistent with the behavior of for loops).
Jun 10 2006