Thread overview
foreach with classes like associative array?
Jan 21, 2012
Matt Soucy
Jan 21, 2012
bearophile
Jan 21, 2012
Ali Çehreli
January 21, 2012
So I was messing around with some code I've been writing today, and I wanted to use a foreach for something, as if it were an associative array. The problem is, I can't find any information on how to do that.
I can't use something like "alias this", because the class I'm writing acts as a wrapper that lets me use string offsets for something that's not string-indexed by default.
I don't see any sort of opApply or similar to do this, and the foreach section of dlang.org doesn't help. Is there a way to do it?
Thank you,
-Matt Soucy
January 21, 2012
Matt Soucy:

> I don't see any sort of opApply or similar to do this, and the foreach section of dlang.org doesn't help. Is there a way to do it?

opApply sounds like the solution for your problem, if you don't need to define a Range. You are allowed to define two or more opApply with different type/number of arguments.

Bye,
bearophile
January 21, 2012
On 01/20/2012 04:53 PM, Matt Soucy wrote:
> So I was messing around with some code I've been writing today, and I
> wanted to use a foreach for something, as if it were an associative
> array. The problem is, I can't find any information on how to do that.
> I can't use something like "alias this", because the class I'm writing
> acts as a wrapper that lets me use string offsets for something that's
> not string-indexed by default.
> I don't see any sort of opApply or similar to do this, and the foreach
> section of dlang.org doesn't help. Is there a way to do it?
> Thank you,
> -Matt Soucy

I have a chapter for this but it hasn't been translated yet:

  http://ddili.org/ders/d/foreach_opapply.html

Translating from there, when there is the following piece of code:

    // What the programmer wrote:
    foreach (/* loop variables */; object) {
        // ... operations ...
    }

The compiler uses the following behind the scenes:

    // What the compiler uses:
    object.opApply(delegate int(/* loop variables */) {
        // ... operations ...
        return termination_code;
    });

You must terminate your loop if termination_code is non-zero. So all you need to do is to write an opApply overload that matches the loop variables:

class C
{
    int[3] keys;
    int[3] values;

    int opApply(int delegate(ref int, ref int) operations) const
    {
        int termination_code;

        for (size_t i = 0; i != keys.length; ++i) {
            termination_code = operations(keys[i], values[i]);
            if (termination_code) {
                break;
            }
        }

        return termination_code;
    }
}

import std.stdio;

void main()
{
    auto c = new C;

    foreach(key, value; c) {
        writefln("%s:%s", key, value);
    }
}

Ali
January 25, 2012
On Fri, 20 Jan 2012 19:53:33 -0500, Matt Soucy <msoucy@csh.rit.edu> wrote:

> So I was messing around with some code I've been writing today, and I wanted to use a foreach for something, as if it were an associative array. The problem is, I can't find any information on how to do that.
> I can't use something like "alias this", because the class I'm writing acts as a wrapper that lets me use string offsets for something that's not string-indexed by default.
> I don't see any sort of opApply or similar to do this, and the foreach section of dlang.org doesn't help. Is there a way to do it?
> Thank you,

From your question, I'm not sure what you are looking for.  It seems you are aware of opApply, but have dismissed it as being usable.

If it helps, here is the reference for how foreach works on various things:

http://www.d-programming-language.org/statement.html#ForeachStatement

Could it be that you want to do this?

class C
{
   int x;
   int y;
}

C c;

foreach(string membername, value; c) {...} // iterate with "x" and "y" as membername

???

I think there is a way to do it with tupleof, but I'm not sure if you can get the member names during iteration.

-Steve