Skip to content

Support foreach when range front converts to a sequence of functions #22828

@ntrel

Description

@ntrel

https://dlang.org/spec/statement.html#front-seq:

Multiple loop variables are allowed if the front property returns a type that expands to a value sequence whose length matches the number of variables

Now that #21296 is fixed, it would be useful to extend the above feature to allow destructuring a sequence of functions (or a sequence of values and functions). Particularly when the function returns by ref, so the corresponding foreach parameter can be ref. Example:

// range for iterating a slice
struct R
{
    char[] a;
    int i = 0;

    @property bool empty() => i == a.length;
    @property auto front()
    {
        struct E
        {
            R* p;

            private alias Seq(A...) = A;
            alias expand = Seq!(index, value);
            alias this = expand;

            @property int index() => p.i;
            @property ref char value() => p.a[p.i];
        }
        return E(&this);
    }
    void popFront() { i++; }
}

char[2] arr = "hi";

void main()
{
    R r = R(arr);
    foreach (e; r)
    {
        // alias this now works
        writeln(e[0], ": ", e[1]);
        e[1] = cast(char)(e[0] + 'a');
    }
    assert(arr == "ab");

    foreach (i, c; r) {} // Error: cannot infer argument types, expected 1 argument, not 2
    foreach (i, ref c; r) {} // Error, should work too
}

A real world use for this would be making object.byKeyValue(aa).front have a type with an alias this to a sequence of its key and value accessor methods. The point of that is so that an element of byKeyValue could be used with foreach destructuring (and also tuple unpacking syntax when @tgehr's implementation is merged):

    auto dict = ["k1": 1, "k2": 2];
    foreach (k, v; dict.byKeyValue) { ... }
    foreach (k, ref v; dict.byKeyValue) { ... } // allows modifying each `v`

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions