Двусторонние итераторы в Nemerle
От: catbert  
Дата: 20.05.10 18:07
Оценка:
Этот пост не фич-реквест, просто интересно обсуждение.

Насколько возможно чисто в макросах реализовать поддержку двусторонних итераторов/генераторов? Это что-то вроде:

Iterator() : Seq[int]
{
   mutable x = 42;
   
   while (true)
   {
       x = yield(x); // yield работает как функция, которая передает аргумент вовне, и возвращает то, что оттуда положат
   }
}

Main() : void
{
    def numbers = Iterator();    

    foreach (i in [1..10])
    {
         WriteLine(numbers[i]); // передаем в Iterator і, получаем оттуда x
    }
}


На выходе получается (вроде как) 42, 1, 2, 3, 4, 5, 6, 7, 8, 9. Фича иногда бывает даже полезна.

Ясно, что как минимум надо будет реализовать интерфейс, похожий на IEnumerable, в котором MoveNext принимает параметр. Ещё, соответственно, нужен макрос для yield. Есть какие-то проблемы, что мешають реализовать данное чудо? (кроме не слишком широкой востребованности)
Re: Двусторонние итераторы в Nemerle
От: Воронков Василий Россия  
Дата: 20.05.10 18:21
Оценка:
Здравствуйте, catbert, Вы писали:

C>Ясно, что как минимум надо будет реализовать интерфейс, похожий на IEnumerable, в котором MoveNext принимает параметр. Ещё, соответственно, нужен макрос для yield. Есть какие-то проблемы, что мешають реализовать данное чудо? (кроме не слишком широкой востребованности)


Мне кажется, если это обобщить, то получатся просто-напросто корутины. Т.е. чтобы можно было не просто возвращаться значение, а передавать контроль в конкретную функцию. По поводу востребованности — хз. Но, мне кажется, корутины вполне можно реализовать поверх генераторов — последние просто должны возвращать некий дескриптор, описывающий, куда именно нужно совершить переход.

Т.е. в твоем примере будет просто две корутины.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Re: Двусторонние итераторы в Nemerle
От: VladD2 Российская Империя www.nemerle.org
Дата: 21.05.10 15:34
Оценка:
Здравствуйте, catbert, Вы писали:

C>Этот пост не фич-реквест, просто интересно обсуждение.


C>Насколько возможно чисто в макросах реализовать поддержку двусторонних итераторов/генераторов? Это что-то вроде:


C>[nemerle]

C>Iterator() : Seq[int]
C>{
C> mutable x = 42;

C> while (true)

C> {
C> x = yield(x); // yield работает как функция, которая передает аргумент вовне, и возвращает то, что оттуда положат
C> }
C>}

Это уже реализовано. Причем дважды.

Для списков есть List comprehensions

В снипетах есть ComputationExpressions.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Двусторонние итераторы в Nemerle
От: catbert  
Дата: 23.05.10 08:59
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Для списков есть List comprehensions


Не очень-то понимаю, причем здесь list comprehensions... Я имею в виду возможность оператора yield возвращать значения.

VD>В снипетах есть ComputationExpressions.


Возможно, yieldcomp как раз можно использовать для реализации. Но он тоже значения вроде бы не возвращает.
Re[3]: Двусторонние итераторы в Nemerle
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.05.10 15:05
Оценка:
Здравствуйте, catbert, Вы писали:

C>Не очень-то понимаю, причем здесь list comprehensions... Я имею в виду возможность оператора yield возвращать значения.


А он разве этого не умеет?

VD>>В снипетах есть ComputationExpressions.


C>Возможно, yieldcomp как раз можно использовать для реализации. Но он тоже значения вроде бы не возвращает.


Тогда опиши свои хотения более подробно. А то я не понял их видимо.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Двусторонние итераторы в Nemerle
От: catbert  
Дата: 25.05.10 20:10
Оценка:
Здравствуйте, VladD2, Вы писали:

C>>Не очень-то понимаю, причем здесь list comprehensions... Я имею в виду возможность оператора yield возвращать значения.


VD>А он разве этого не умеет?


Ну, yield вроде как выталкивает (push) значения в вызывающую процедуру. А двусторонний yield может его еще и вытягивать (pull) из вызывающей процедуры. Я думал, Руби так умеет, но там, насколько я погуглил, для достижения pull-эффекта просто yield-ятся ссылки на переменные.

Все иллюстрируется кодом:

def x = yield(a);


То есть, yield становится функцией (точнее, выражением) и возвращает значения.

Такое реализовано в Python 2.5 и хорошо описано тут: http://www.python.org/dev/peps/pep-0342/ В принципе, в том документе много дополнительных фишек описано: возможность останавливать итераторы, вызывать в них исключения.

Двусторонние итераторы — это почти сопрограммы (coroutines), не хватает только возможности для итератора выбирать, в какую процедуру yield-ить. А от сопрограмм, мне кажется, и до продолжений (continuations) в отдельно взятых классах недалеко
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.