Как сделать объект (класс) доступным в D? - PullRequest
7 голосов
/ 15 июня 2010

как я могу сделать класс пригодным для использования в выражении foreach?

Класс содержит ассоциативный массив (например, string [string]). Поэтому оператор foreach использует этот массив в качестве источника.

Так вот что я хочу:

auto obj = new Obj();
foreach (key, value; obj)
{
    ...
}

Нужно ли реализовывать подобный интерфейс?

EDIT:

Решение:

public int opApply(int delegate(ref string, ref Type) dg)
{
    int result = 0;

    foreach (ref key, ref value; data)
    {
        result = dg(key, value);
        if (result != 0)
        {
            break;
        }
    }

    return result;
}

То же самое сделано для public int opApply (int делегат (ref Type) dg).

Ответы [ 2 ]

4 голосов
/ 15 июня 2010

D1 :

class Foo
{
    uint array[2];

    int opApply(int delegate(ref uint) dg)
    {
        int result = 0;

        for (int i = 0; i < array.length; i++)
        {
            result = dg(array[i]);
            if (result)
                break;
        }
        return result;
    }
}

D2 :

Итерация по объектам структуры и класса может выполняться с диапазонами, что означает, что должен быть задан [набор] свойств:

3 голосов
/ 17 июня 2010

Решение, опубликованное OP, является допустимым, но в D2 есть другое решение с другим набором компромиссов. Итерацию в D можно разделить на внутреннюю итерацию, которая обрабатывается opApply, и внешнюю итерацию, которая обрабатывается диапазонами.

Внутренняя итерация дает итерируемому объекту контроль над стеком вызовов. Это позволяет, например, использовать рекурсию для объекта, итерируемого без сохранения явного стека, но делает невозможным итерацию по нескольким структурам в шаге блокировки. Внешняя итерация делает обратное.

Внешняя итерация осуществляется через диапазоны. Диапазон - это любой класс или структура, которые определяют три метода: front() предоставляет доступ к первому элементу в диапазоне, popFront() увеличивает диапазон и empty() возвращает true, если диапазон пуст. Если диапазон бесконечен, пустой может быть объявлен как константа вместо функции-члена. Таким образом, вызывающая сторона контролирует стек вызовов, который может быть хорошим или плохим в зависимости от ситуации.

Вот пример использования диапазонов для итерации:

/**This struct lazily produces all Fibonacci numbers.*/
struct Fibonacci {
    ulong num1 = 0;
    ulong num2 = 1;

    ulong front() {
        return num1 + num2;
    }

    void popFront() {
        auto newNum2 = num1 + num2;
        num1 = num2;
        num2 = newNum2;
    }

    // A range of Fibonacci numbers is infinite.
    enum bool empty = false; 
}
...