extending foreach for keyed ranges and other usage of datastructures
monkyyy
crazymonkyyy at gmail.com
Wed May 15 20:27:12 UTC 2024
extend the api of foreach to allow for `foreach(key,value;data)`
for user data types,
and user defined "autodecoding"
### related debates
the (unnesery) deperacation of "implict casts" of array indexes
to int
https://forum.dlang.org/thread/qdsypzjwptbebffktohx@forum.dlang.org
key'd ranges in general
https://forum.dlang.org/thread/akczwyrmlpocihmaitbz@forum.dlang.org
### definitions
keyd range: a struct that defines the functions
front,popFront,empty and key
autodecoding: when a data structure is implicitly transformed
into a range by a imported function and ufcs (not string specific)
foreach header: the part of the foreach call that comes before
the ;
### priority
1. if the template header and data combo are currently valid,
dont change behavior(whatever that looks like)
2. if the data is a keyd range but the foreach header has a key;
define key to be range.key and value to be range.front; handle
ref if possible
3. if data is not a range, attempt to call opSlice to see if
thats a range (static arrays)
4. if data does not have an opSlice, "autodecode"
`data.toRange!(details from foreach header)`
### foreach header parsing
because ref isnt on types I dont believe you can pass "ref int"
into a template, and maybe theres something about named
arguments, I believe this should be handled with strings.
unattributed arguments are replaced with void, so the user can
handle hard cases tuples as they wish(2d iteration, or zipped
ranges)
`foreach(int k,value:ref @safe v;...)` would be parsed as
("int","value:ref @safe") Im unsure what user code does with
"@safe" but let the user figure it out
`foreach(a,b,c,d,e,f,g;...)` would be parsed as
(void,void,void,void,void,void)
### keyd range example code
```d
struct strangecounter{
int front;
int last;
void popFront(){front++;}
int key()=>front*front;
bool empty()=> last>=front;
}
foreach(k,v;strangecounter(0,10)){
writeln(k,":",v);//0:0, 1:1, 4:2,9:3.....
}
```
`foreach(ref k,v;strangecounter(0,10))` would fail to compile,
some complaint about lvalues or suggesting the user to define a
`torange!("ref",void)`
`foreach(k,ref v;strangecounter(0,10))` would compile
`foreach(size_t k,v;strangecounter(0,10))` would fail to compile,
suggesting the user to define a `torange!("size_t",void)`
`foreach(a,b,c;strangecounter(0,10))` would fail to compile, and
suggesting the user define a torange!(void,void,void)
`foreach(v;strangecounter(0,10))` would compile (using keys are
optional)
### torange example code
handling int indexing
```d
auto torange(string s:"int",T)(ref T[] array){
struct myrange{
int key_;
auto key()=>key_;//unref's key
auto front()=>array[key];
auto popFront(){key_++;}
auto empty()=>arra.length>=key;
}
return myrange;
}
foreach(int i,v;array){//compiles
```
More information about the dip.ideas
mailing list