On Monday, 21 September 2015 at 15:38:40 UTC, French Football wrote:
Going through a book on coding in D, http://ddili.org/ders/d.en/foreach.html , I find the following very useful feature:

When two names are specified in the names section [with a plain array], they represent an automatic counter and the value of the element, respectively:
    foreach (i, element; array) {
        writeln(i, ": ", element);
    }

I understand that foreach is built on top of a for loop... I'm just wondering why I can't access the automatic counter from a doubly linked list, or an associative array, or some range? It's pretty common for me to have to rewrite foreach loops to be for loops when I get to the bottom and realize I need to know where in the sequence I am...

That's because this isn't really a counter. It makes more sens if you think of it as:

    foreach (key, value ; array) {
        ...
    }

In the case of an array, the key to access directly a value is its index, and the array is read in its natural order so the 'key' part acts as a counter. If array is an associative array instead of an array, then you get the key and value as well.

If you want a counter, you want to look at std.range.enumerate() which takes a range and returns a tuple (counter, element). The following example demonstrates the two usages with associative arrays:

    void main(string[] args)
    {
        import std.stdio;
        import std.range;

        bool[int] aa = [0:true, 1:true, 2:false];

        writeln("Get keys and values from an AA");
        foreach (key, value ; aa) {
            writeln(key, ": ", value);
        }
        writeln;

        writeln("Get a counter and the key of an AA");
        foreach (count, key ; aa.byKey.enumerate) {
writeln("count: ", count, " key: ", key, " value: ", aa[key]);
        }
    }

Note that contrary to languages such as PHP, D's associative arrays are unordered so you can't use this counter as an index.

Reply via email to