www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - CT foreaches

reply monkyyy <crazymonkyyy gmail.com> writes:
```d
import std;
void foo(int i:0)()=>"foo".writeln;
void foo(int i:1)()=>"bar".writeln;
void foo(int i:2)()=>"foobar".writeln;
void main(){
	foreach(i,alias b; AliasSeq!("foo","bar")){
		pragma(msg, b.stringof);
	        break;
	}
	pragma(msg,"---");
	foreach(i,enum b; AliasSeq!("foo","bar")){
		pragma(msg, b.stringof);
		break;
	}
	pragma(msg,"---");
	static foreach(i;0..3){
		pragma(msg, i.stringof);
		//break; //the scope error
	}
	pragma(msg,"---");
	foreach(enum i;0..3){// ERROR ISNT CT. ISNT AN ENUM
		pragma(msg, i.stringof);
		//foo!i; //doesnt compile
		break;
	}
}
```

Theres bugs and unintended features here :D ; alias foreach is 
undocumented even in the template book; the dip 1010 code block 
that *may* be why this behavior exists doesnt actaully work, the 
docs were wrong a week ago

etc. etc.

currently I believe:

a) static makes it a block, makes enum or alias infered
b) enum or alias of aliasSeq, whoever made thought there be an 
upgrade to fully generalize the syntax
c) the dip 1010 section was ambiguous if it was real causing enum 
to be ignored

anyone got any code blocks?
Aug 01
next sibling parent reply Nick Treleaven <nick geany.org> writes:
On Friday, 1 August 2025 at 13:51:43 UTC, monkyyy wrote:
 ```d
 import std;
 void foo(int i:0)()=>"foo".writeln;
 void foo(int i:1)()=>"bar".writeln;
 void foo(int i:2)()=>"foobar".writeln;
 void main(){
 	foreach(i,alias b; AliasSeq!("foo","bar")){
 		pragma(msg, b.stringof);
 	        break;
 	}
 	pragma(msg,"---");
 	foreach(i,enum b; AliasSeq!("foo","bar")){
 		pragma(msg, b.stringof);
 		break;
 	}
 	pragma(msg,"---");
 	static foreach(i;0..3){
 		pragma(msg, i.stringof);
 		//break; //the scope error
 	}
Up to here is all as expected, right?
 	pragma(msg,"---");
 	foreach(enum i;0..3){// ERROR ISNT CT. ISNT AN ENUM
 		pragma(msg, i.stringof);
 		//foo!i; //doesnt compile
You're using runtime foreach here. It's only expanded at compile-time when the aggregate is a sequence - as the spec says. The confusing thing is that enum there is silently ignored. I think we could add an error for that.
 		break;
 	}
 }
 ```

 Theres bugs and unintended features here :D ; alias foreach is 
 undocumented even in the template book;
That hasn't been updated in 8 years.
 the dip 1010 code block that *may* be why this behavior exists 
 doesnt actaully work, the docs were wrong a week ago

 etc. etc.

 currently I believe:

 a) static makes it a block, makes enum or alias infered
 b) enum or alias of aliasSeq, whoever made thought there be an 
 upgrade to fully generalize the syntax
Not sure what you mean for (b).
 c) the dip 1010 section was ambiguous if it was real causing 
 enum to be ignored

 anyone got any code blocks?
Aug 01
parent reply monkyyy <crazymonkyyy gmail.com> writes:
On Friday, 1 August 2025 at 15:15:35 UTC, Nick Treleaven wrote:
 
 Up to here is all as expected, right?
No, `foreach(alias` is functionally undocumented (dip 1010 is not exactly common reading material for current year, and if you did read it, it would have errors or misunderstanding for what eventually happened) and extremely rare
 	pragma(msg,"---");
 	foreach(enum i;0..3){// ERROR ISNT CT. ISNT AN ENUM
 		pragma(msg, i.stringof);
 		//foo!i; //doesnt compile
You're using runtime foreach here. It's only expanded at compile-time when the aggregate is a sequence - as the spec says.
`foreach(enum i;0..3){` is directly from the dip 1010 its unclear from the responce if it was accepted or rejected
 b) enum or alias of aliasSeq, whoever made thought there be an 
 upgrade to fully generalize the syntax
Not sure what you mean for (b).
dip 1010 was optimistic about near term upgrades to static foreach; static break and continue ---
 The confusing thing is that enum there is silently ignored. I 
 think we could add an error for that.
That would be a breaking change now, most code swapped from runtime to ct should continue working tho, better to just implement it
Aug 01
parent reply Nick Treleaven <nick geany.org> writes:
On Friday, 1 August 2025 at 15:47:47 UTC, monkyyy wrote:
 On Friday, 1 August 2025 at 15:15:35 UTC, Nick Treleaven wrote:
 
 Up to here is all as expected, right?
No, `foreach(alias` is functionally undocumented
Thanks, fix: https://github.com/dlang/dlang.org/pull/4279
 	pragma(msg,"---");
 	foreach(enum i;0..3){// ERROR ISNT CT. ISNT AN ENUM
 		pragma(msg, i.stringof);
 		//foo!i; //doesnt compile
You're using runtime foreach here. It's only expanded at compile-time when the aggregate is a sequence - as the spec says.
`foreach(enum i;0..3){` is directly from the dip 1010 its
That's under the 'Limitations of this DIP / possible future improvements' section: https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1010.md#allowing-alias-and-enum-on-regular-foreach-loop-variables
 unclear from the responce if it was accepted or rejected
That DIP says 'Status: Accepted' at the top.
 b) enum or alias of aliasSeq, whoever made thought there be 
 an upgrade to fully generalize the syntax
Not sure what you mean for (b).
dip 1010 was optimistic about near term upgrades to static foreach; static break and continue ---
 The confusing thing is that enum there is silently ignored. I 
 think we could add an error for that.
That would be a breaking change now, most code swapped from runtime to ct should continue working tho, better to just implement it
Not really, no one should have used enum/alias with a non-static ForeachRangeStatement because (as you pointed out), it wasn't in the spec. If they did use it, they'd probably realize that those storage classes had no effect.
Aug 01
parent reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Friday, 1 August 2025 at 16:45:04 UTC, Nick Treleaven wrote:
 On Friday, 1 August 2025 at 15:47:47 UTC, monkyyy wrote:
 On Friday, 1 August 2025 at 15:15:35 UTC, Nick Treleaven wrote:
 The confusing thing is that enum there is silently ignored. I 
 think we could add an error for that.
That would be a breaking change now, most code swapped from runtime to ct should continue working tho, better to just implement it
Not really, no one should have used enum/alias with a non-static ForeachRangeStatement because (as you pointed out), it wasn't in the spec. If they did use it, they'd probably realize that those storage classes had no effect.
Making non-static `foreach (enum x; l .. u)` an error would be fairly easy. It’s just a parser issue. The error message could say: Use `static foreach`. I’ll have a go on this.
Aug 01
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 8/1/25 20:06, Quirin Schroll wrote:
 On Friday, 1 August 2025 at 16:45:04 UTC, Nick Treleaven wrote:
 On Friday, 1 August 2025 at 15:47:47 UTC, monkyyy wrote:
 On Friday, 1 August 2025 at 15:15:35 UTC, Nick Treleaven wrote:
 The confusing thing is that enum there is silently ignored. I think 
 we could add an error for that.
That would be a breaking change now, most code swapped from runtime to ct should continue working tho, better to just implement it
Not really, no one should have used enum/alias with a non-static ForeachRangeStatement because (as you pointed out), it wasn't in the spec. If they did use it, they'd probably realize that those storage classes had no effect.
Making non-static `foreach (enum x; l .. u)` an error would be fairly easy. It’s just a parser issue. The error message could say: Use `static foreach`. I’ll have a go on this.
For reference: https://github.com/dlang/dmd/issues/21630 https://github.com/dlang/dmd/pull/21631 https://github.com/dlang/dmd/pull/21633 My PR is currently blocked on a weird CI failure, not sure where it is coming from.
Aug 01
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 8/1/25 15:51, monkyyy wrote:
 ```d
 import std;
 void foo(int i:0)()=>"foo".writeln;
 void foo(int i:1)()=>"bar".writeln;
 void foo(int i:2)()=>"foobar".writeln;
 void main(){
      foreach(i,alias b; AliasSeq!("foo","bar")){
          pragma(msg, b.stringof);
              break;
      }
      pragma(msg,"---");
      foreach(i,enum b; AliasSeq!("foo","bar")){
          pragma(msg, b.stringof);
          break;
      }
These behave like lined out in Proposal 1 of DIP 1010. Code snippets from the DIP: ```d foreach (enum v; AliasSeq!(x,y,z)) { ... } ``` ```d foreach (alias v; AliasSeq!(x,y,z)) { } ``` https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1010.md#proposal-1-allow-enum-and-alias-variables-for-unrolled-foreach-statements
      pragma(msg,"---");
      static foreach(i;0..3){
          pragma(msg, i.stringof);
          //break; //the scope error
      }
      pragma(msg,"---");
This is just a standard `static foreach`.
      foreach(enum i;0..3){// ERROR ISNT CT. ISNT AN ENUM
          pragma(msg, i.stringof);
          //foo!i; //doesnt compile
          break;
      }
 }
 ```
 ...
This one is a bug, quote from DIP1010:
 Currently, it is an error to use alias or enum on a regular foreach loop:

 ```d
 foreach (enum i; 0 .. 3){ ... } // error
 ```

 It has been suggested that this should instead unroll the loop, such 
that it becomes equivalent to:
 ```d
 foreach (enum i; AliasSeq!(0,1,2)) { ... }
 ```
https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1010.md#allowing-alias-and-enum-on-regular-foreach-loop-variables https://github.com/dlang/dmd/issues/21630 https://github.com/dlang/dmd/pull/21631
Aug 01