Вот честно, не флейма ради, но недавно подобный вопрос поставил меня в тупик. В качестве наглядного примера можно взять итераторы в C# или даже более продвинутую реализацию. Неважно.
Фактически все задачи, которые выполняются через итераторы, не менее успешно выполняются и через функцию-замыкание. Насколько я понимаю, в том же Руби итераторы по сути и представляют собой некий сахар для подобного.
Попробую объяснить, что я имею в виду. Положим, некий код вида:
IEnumerable<Int32> Range(int start, int end)
{
var e = end + 1;
for (var i = start; i < e; i++)
yield return i;
}
foreach (var i in Range(0, 100)) {
//Do something
}
Можно переписать вот так:
void Range(int start, int end, Action<Int32> fun)
{
var e = end + 1;
for (var i = start; i < e; i++)
fun(i);
}
Можно представить так и работу с бесконечными последовательностями, если действие будет описывать как Func<T,Int32,Boolean>, где второй параметр — порядковый номер элемента, а первый сам элемент. Возвращается же флажок, по которому определяются следует ли нам продолжать. Создавать такую функцию можно через простейший комбинатор вида:
Func<T,Int32,Boolean> Create(Action<T> fun, int take)
{
var t = take + 1;
return (e, i) => {
if (i < t) {
fun(e);
return true;
}
else
return false;
};
}
Т.е. с точки зрения юзабилити это, конечно, менее удобно, но вот, собственно, и все.
В принципе у итераторов как частного случая корутин должны быть более широкие применения вроде как, но все, о чем я могу подумать, прекрасно выражается через ФВП. Причем вариант с ФВП отлично дружит с continuation-ами, с которыми те же C#-вые итераторы не дружат совсем.
Т.е. итераторы просто сахар? Зачем они нужны?