On Wednesday, 13 March 2024 at 22:16:52 UTC, rkompass wrote:
I want to make a custom dictionary that I may iterate through with foreach. Several times. What I observe so far is that my dict as a simple forward range is exhausted after the first foreach and I have to deeply copy it beforehand.
With a simple associative array the exhaustion is not observed.
Is there a (hopefully simple) way to make this automatic/transparent? Of course
I need to use the struct.
Can I add a save member function? If yes: How? Or is there an operator that is used in the foreach initialization that I may overload in this struct?

you need to seperate the range state from the data

```d
import std;
auto tuple(T...)(T t){
    struct tuple{
        T me; alias me this;
    }
    return tuple(t);
}
struct mydict(T,S){
        T[S] dct;
        void opAssign(mydict rhs) {
                writeln("--opAssign--");
                foreach (k; rhs.dct.keys)  // do a deep copy
                        dct[k] = rhs.dct[k];
        }
    auto opSlice(){
        struct range{
            T[S]* parent;
            int i;
auto front()=> tuple(parent.keys[i],(*parent)[parent.keys[i]]);
            auto popFront()=>i++;
            auto empty()=>parent.keys.length<=i;
        }
        return range(&this.dct);
    }
}

void main() {

        mydict!(string,string) md, md2;
        md.dct = ["h":"no", "d":"ex", "r": "cow"];
        md2 = md;             // md2.opAssign(md)
        foreach (k, v; md[])
                writeln("key: ", k, "val: ", v);
        writeln("----------");
foreach (k, v; md[]) // does not work with md again, md is exhausted
                writeln("key: ", k, "val: ", v);
}
```

Reply via email to