Здравствуйте, Tanker, Вы писали:
T>Здравствуйте, samius, Вы писали:
T>>>Конечно вернет, а что тут особенного ? При чем вычислится ровно один элемент. А если например ты будешь вызывать вот так Any(x => x == "тарелка борща"); то никогда не вернет.
S>>За счет чего while(true) остановится на одном элементе?
T>Очевидно, за счет средств ОС — потоки, файберы. Никакого обмана.
К сожалению, не вижу никакого повода для того что бы средства ОС вмешались в цикл while(true) и на потоках и файберах обеспечили бы разрывность его выполнения. Этот цикл в коде на C# не отличается от многих других, которые не нуждаются в файберах.
Здравствуйте, samius, Вы писали:
T>>Очевидно, за счет средств ОС — потоки, файберы. Никакого обмана. S>К сожалению, не вижу никакого повода для того что бы средства ОС вмешались в цикл while(true) и на потоках и файберах обеспечили бы разрывность его выполнения. Этот цикл в коде на C# не отличается от многих других, которые не нуждаются в файберах.
Если ты забыл, то разговор был про "хотя бы один способ эмуляции yield return без поддержки языка".
А вот поводов использовать потоки и файберы хотя бы для генераторов выше крыши даже в С#, хочешь, создай новый тред,а я покажу примеры, правда может не сейчас а как водится через пару месяцев.
Здравствуйте, Tanker, Вы писали:
T>Здравствуйте, samius, Вы писали:
T>>>Очевидно, за счет средств ОС — потоки, файберы. Никакого обмана. S>>К сожалению, не вижу никакого повода для того что бы средства ОС вмешались в цикл while(true) и на потоках и файберах обеспечили бы разрывность его выполнения. Этот цикл в коде на C# не отличается от многих других, которые не нуждаются в файберах.
T>Если ты забыл, то разговор был про "хотя бы один способ эмуляции yield return без поддержки языка".
Я пока ни одного не увидел. Начал читать статью по твоей ссылке про корутины на MC++. T>А вот поводов использовать потоки и файберы хотя бы для генераторов выше крыши даже в С#, хочешь, создай новый тред,а я покажу примеры, правда может не сейчас а как водится через пару месяцев.
Я же не утверждал что нет поводов использовать потоки и файберы. Я про то, что на мой взгляд цикл из твоего примера ничем не отличается от любых других циклов без yield, await и т.п. Мне непонятно, почему он будет выполняться частями.
Здравствуйте, Tanker, Вы писали:
T>Здравствуйте, Sinclair, Вы писали:
I>>>Это можно эмулировать десятком способов, не было только языковой поддержки. Например в winapi есть такая вещь, как файберы — очень интересная штукенция. S>> Покажите мне, как эмулировать Enumerable.TakeWhile на файберах. Его устройство в терминах yield return мне понятно.
T>Точно так же, как и без файберов
Если "точно так же", то в чём смысл использовать файберы? T> Надеюсь идея ясна:
Нет. Без описания типа вашего c, или хоты бы без кода функций yield() идея совершенно неясна.
Ну и для понятности стоило бы всё-таки привести код Enumerable.TakeWhile, а не пару малопонятных корутин.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, samius, Вы писали:
T>>Если ты забыл, то разговор был про "хотя бы один способ эмуляции yield return без поддержки языка". S>Я пока ни одного не увидел. Начал читать статью по твоей ссылке про корутины на MC++.
T>>А вот поводов использовать потоки и файберы хотя бы для генераторов выше крыши даже в С#, хочешь, создай новый тред,а я покажу примеры, правда может не сейчас а как водится через пару месяцев. S>Я же не утверждал что нет поводов использовать потоки и файберы. Я про то, что на мой взгляд цикл из твоего примера ничем не отличается от любых других циклов без yield, await и т.п. Мне непонятно, почему он будет выполняться частями.
Ты напиши по русски, а то я не понимаю какой ещ цикл ты хочешь увидеть. Вроде бесконечный цикл и any я тебе показал
Здравствуйте, Tanker, Вы писали:
T>Здравствуйте, samius, Вы писали:
S>>Я же не утверждал что нет поводов использовать потоки и файберы. Я про то, что на мой взгляд цикл из твоего примера ничем не отличается от любых других циклов без yield, await и т.п. Мне непонятно, почему он будет выполняться частями.
T>Ты напиши по русски, а то я не понимаю какой ещ цикл ты хочешь увидеть. Вроде бесконечный цикл и any я тебе показал
Вроде как уже написал. И по-русски.
Здравствуйте, Sinclair, Вы писали:
T>>Точно так же, как и без файберов S>Если "точно так же", то в чём смысл использовать файберы?
Смысл в том, что короутины получаеются взрослые, со всеми прибамбасами — рекурсией, вызовом других короутин и тд и тд. В C# скажем нет возможности сделать var x = yield; кроме как разводить грязь навроде
var request = new Request<string>();
...
yield return request;
var x = request.Value;
T>> Надеюсь идея ясна: S>Нет. Без описания типа вашего c, или хоты бы без кода функций yield() идея совершенно неясна.
public void yield(R value)
{
_next.Send(value); // отдать по цепочке
}
public R yield()
{
return _input.Get(); // блокирующий ресурс, будит вызывающий код, для примера см BlockingCollection
}
c это просто враппер вокруг короутины для доступа к методам yield
S>Ну и для понятности стоило бы всё-таки привести код Enumerable.TakeWhile, а не пару малопонятных корутин.
Мне комбинаторs не нужены, лень тестировать и отлаживать, вот, накидал приблизительный код, адаптировал из имеющихся комбинаторов и тестов (where + select). Вобще комбинаторы здесь баловство, все хочется выпилить полноценный Linq2Co, но руки не дойдут
public static Co<T> TakeWhile<T>(this Co<T> pipe, Func<T, bool> predicate)
{
return pipe.Then(c =>
{
while (true)
{
var x = c.yield(); // read from inputif (predicate(option.Value))
{
c.yield(option.Value); // write to outputcontinue;
}
break;
}
});
}
...
[TestMethod]
public void LinqSimpleTest()
{
var source = Co.New<string>();
var result = new StringBuilder();
var x = (from s in source where isNumber(s) select s).TakeWhile(x => x != "6").Then(n => saveTo(result));
f.Send("1");
f.Send("2");
f.Send("text");
f.Send("4");
f.Send("5");
f.Send("6");
f.Close();
Assert.AreEqual("1245", result.ToString());
}
Здравствуйте, samius, Вы писали:
S>>>Я же не утверждал что нет поводов использовать потоки и файберы. Я про то, что на мой взгляд цикл из твоего примера ничем не отличается от любых других циклов без yield, await и т.п. Мне непонятно, почему он будет выполняться частями.
T>>Ты напиши по русски, а то я не понимаю какой ещ цикл ты хочешь увидеть. Вроде бесконечный цикл и any я тебе показал S>Вроде как уже написал. И по-русски.
Потому что функция выполняется в отдельном потоке. Каждый вызов yield явно останавливает с помощнь Monitor.Wait а каждый вызов MoveNext итератора пробуждает xthtp Monitor.PulseAll.
Здравствуйте, Tanker, Вы писали:
T>Здравствуйте, samius, Вы писали:
T>Потому что функция выполняется в отдельном потоке. Каждый вызов yield явно останавливает с помощнь Monitor.Wait а каждый вызов MoveNext итератора пробуждает xthtp Monitor.PulseAll.
Вот теперь идея понятна, спасибо. Разве что я не соглашусь что это эмуляция yield return.
Так же, наверное можно, на цикле сообщений сэмулировать. Все-таки это эмуляция семантики, но не конкретного решения с машиной состояний и замыканием.
Здравствуйте, samius, Вы писали:
T>>Потому что функция выполняется в отдельном потоке. Каждый вызов yield явно останавливает с помощнь Monitor.Wait а каждый вызов MoveNext итератора пробуждает xthtp Monitor.PulseAll. S>Вот теперь идея понятна, спасибо. Разве что я не соглашусь что это эмуляция yield return. S>Так же, наверное можно, на цикле сообщений сэмулировать. Все-таки это эмуляция семантики, но не конкретного решения с машиной состояний и замыканием.
Я эмулировал не шарповкий yield, а питоновские короутины. Генератор это баловства ради прямо сегодня написал, что бы разобраться с монитором.
Здравствуйте, Tanker, Вы писали:
T>Здравствуйте, samius, Вы писали:
S>>Так же, наверное можно, на цикле сообщений сэмулировать. Все-таки это эмуляция семантики, но не конкретного решения с машиной состояний и замыканием.
T>Я эмулировал не шарповкий yield, а питоновские короутины. Генератор это баловства ради прямо сегодня написал, что бы разобраться с монитором.
Здравствуйте, Tanker, Вы писали:
T>Смысл в том, что короутины получаеются взрослые, со всеми прибамбасами — рекурсией, вызовом других короутин и тд и тд. В C# скажем нет возможности сделать var x = yield; кроме как разводить грязь навроде T>
T>var request = new Request<string>();
T>...
T>yield return request;
T>var x = request.Value;
T>
Брр. Во-первых, мы говорили не про корутины, а про Enumerable Pattern.
Во-вторых, в C# скажем есть возможность сделать
var x = await getX;
T>
T> public void yield(R value)
T> {
T> _next.Send(value); // отдать по цепочке
T> }
T> public R yield()
T> {
T> return _input.Get(); // блокирующий ресурс, будит вызывающий код, для примера см BlockingCollection
T> }
T>
Кто такие _next и _input? Как устроены Send и Get?
У меня складывается впечатление, что вы пытаетесь переизобрести RxLib, совместив IObservable и IEnumerable в вашем Co.
T>c это просто враппер вокруг короутины для доступа к методам yield
А что завёрнуто внутрь этого враппера?
S>>Ну и для понятности стоило бы всё-таки привести код Enumerable.TakeWhile, а не пару малопонятных корутин.
T>Мне комбинаторs не нужены, лень тестировать и отлаживать, вот, накидал приблизительный код, адаптировал из имеющихся комбинаторов и тестов (where + select). Вобще комбинаторы здесь баловство, все хочется выпилить полноценный Linq2Co, но руки не дойдут
T>
T> public static Co<T> TakeWhile<T>(this Co<T> pipe, Func<T, bool> predicate)
T> {
T> return pipe.Then(c =>
T> {
T> while (true)
T> {
T> var x = c.yield(); // read from input
T> if (predicate(option.Value))
T> {
T> c.yield(option.Value); // write to output
T> continue;
T> }
T> break;
T> }
T> });
T> }
T>...
T> [TestMethod]
T> public void LinqSimpleTest()
T> {
T> var source = Co.New<string>();
T> var result = new StringBuilder();
T> var x = (from s in source where isNumber(s) select s).TakeWhile(x => x != "6").Then(n => saveTo(result));
T> f.Send("1");
T> f.Send("2");
T> f.Send("text");
T> f.Send("4");
T> f.Send("5");
T> f.Send("6");
T> f.Close();
T> Assert.AreEqual("1245", result.ToString());
T> }
T>
1. Похоже на опечатку. Вы имели в виду var f = (from s in ...), и x.Value?
2. А чего так сложно-то? В оригинале мы имеем
public static IEnumerable<T> TakeWhile<T>(this IEnumerable<T> source, Predicate<T> predicate)
{
foreach(var x in source)
if (predicate(x))
yield return x;
else
break;
}
3. У вас всё ещё не видно поддержки стандартных енумераторов. Это ограничивает интероперабельность со стандартными коллекциями. Или она таки есть, но я её не вижу?
4. Енумераторное решение помимо Send и Get работает с IDisposable, гарантируя освобождение ресурсов. У вас как с поддержкой исключений? Получит ли корутина аналог Dispose() в тот момент, когда вызывающая её корутина решила "хватит" (как это происходит в настоящем TakeWhile)?
5. Могу ли я скормить один и тот же источник в два разных TakeWhile? Вот так:
[TestMethod]
public void LinqSimpleTest()
{
var source = new List<string>();
var result = new StringBuilder();
var x1 = (from s in source where isNumber(s) select s).TakeWhile(x => x != "6").GetEnumerator();
var x2 = (from s in source where isNumber(s) select s).TakeWhile(x => x != "2").GetEnumerator();
source.AddRange(new string[] {"1", "2", "text", "4", "5", "6"});
foreach(var i1 in x1)
Console.WriteLn(i1);
foreach(var i2 in x2)
Console.WriteLn(i2);
Ввша реализация с _next.Send() меня настораживает.
Также настораживает то, что я не вижу способа в корутине работать с разнотипными значениями. У вас оба yield имеют тип T. Непонятно, как мне сделать
async string FormatUser(Task<string> name, Task<int> age)
{
return await name + ", " await age + ", лет";
}
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
T>Но по моему это глупусть, на потоках намного проще а издержки те же самые.
Насчёт издержек есть внутренне чувство ошибочности. AFAIR, файберы а) не отжирают по мегабайту стека на рыло в адресном пространстве процесса и б) значительно дешевле переключают контекст.
Скажем, в серверном приложении заводить целый отдельный поток каждый раз, как кто-то напишет from i in items where i.name.Length > 0 выглядит несколько страшным.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Во-вторых, в C# скажем есть возможность сделать S>
S>var x = await getX;
S>
Здесь тоже есть такая возможность, но это я не реализовывал. Цель написания либы это эксперименты с короутинами и мониторами
S>Кто такие _next и _input? Как устроены Send и Get?
_next это следующая короутина. _input это вход, просто блокирующий ресурс. Для примера можно взять BlockingCollection<>, будет оно самое, только я написал свой, с целью разобраться с мониторами.
S>У меня складывается впечатление, что вы пытаетесь переизобрести RxLib, совместив IObservable и IEnumerable в вашем Co.
Короутины древнее не только IEnumerable, но всех дотнетов, виндовсов и линуксов вместе взятых. Так что скорее await и yield return выглядят попыткой изобрести короутины.
Скажем на короутинах эвенты и коллекции можно обрабатывать одним и тем же кодом.
Кроме того, RX это реактивный код, а мне нужен императивный.
T>>c это просто враппер вокруг короутины для доступа к методам yield S>А что завёрнуто внутрь этого враппера?
Изоляция чисто для интелисенса, а то короутина поддерживает IEnumerable например.
T>>Мне комбинаторs не нужены, лень тестировать и отлаживать, вот, накидал приблизительный код, адаптировал из имеющихся комбинаторов и тестов (where + select). Вобще комбинаторы здесь баловство, все хочется выпилить полноценный Linq2Co, но руки не дойдут
S>1. Похоже на опечатку. Вы имели в виду var f = (from s in ...), и x.Value?
Да, опечатка. Я говорил, что это приблизительный код.
S>2. А чего так сложно-то? В оригинале мы имеем
Потому что это все таки эмуляция короутин, а не сами короутины. Я не в курсе всей математики короутин, потому не могу сказать, реализовал ли я общий случай, взяв за основу питоновские короутины.
S>3. У вас всё ещё не видно поддержки стандартных енумераторов. Это ограничивает интероперабельность со стандартными коллекциями. Или она таки есть, но я её не вижу?
В моем первом примере про генератор все это есть. Пока только короутина и генератор это разные классы, у меня тут хаос и шатание, три разных варианта пробую. Но вобще достаточно одного.
S>4. Енумераторное решение помимо Send и Get работает с IDisposable, гарантируя освобождение ресурсов. У вас как с поддержкой исключений? Получит ли корутина аналог Dispose() в тот момент, когда вызывающая её корутина решила "хватит" (как это происходит в настоящем TakeWhile)?
С исключениями посложнее из за отдельного потока. Исключения буду делать по мере необходимости. Пока "я пейшу бес ашыбок".
S>5. Могу ли я скормить один и тот же источник в два разных TakeWhile? Вот так:
Конечно. Но вообще говоря linq это не то, ради чего нужны короутины. Меня прежде всего интересует возможность делать энергичный императивный код ленивым.
S>Ввша реализация с _next.Send() меня настораживает.
Это именно то ради чего я начал изучать короутины
S>Также настораживает то, что я не вижу способа в корутине работать с разнотипными значениями. У вас оба yield имеют тип T.
Да, библиотечка далека от завершения. Я на ней в основном проверяю кое какие идеи, это не продакшн код. Правда публиковать его не буду, хочу все таки опробовать в продакшне.
Здравствуйте, Sinclair, Вы писали:
T>>Но по моему это глупусть, на потоках намного проще а издержки те же самые. S>Насчёт издержек есть внутренне чувство ошибочности. AFAIR, файберы а) не отжирают по мегабайту стека на рыло в адресном пространстве процесса и б) значительно дешевле переключают контекст. S>Скажем, в серверном приложении заводить целый отдельный поток каждый раз, как кто-то напишет from i in items where i.name.Length > 0 выглядит несколько страшным.
Дотнет в общем случае не поддерживает файберы и требует слишком большого количества телодвижений:
Since fibers running managed code all exist on the same thread, switching between them causes problems for the exception handlers on a "managed" fiber. To avoid this I hook in the CLR host from unmanaged code, and using four undocumented APIs I inform the runtime about the presence of fibers, and notify it just before switching between fibers.
У файбера как минимум свой стек + fiber local storage. А мегабайт стека у потока можно и уменьшить, это как раз и не проблема. Переключение потоков много времени занимает, я как нибудь сделаю замеры, сравню с питоновской динамикой, не думаю что результаты будут провальными.
Либа то не ради Linq2Co начиналась, Linq это побочный эффект. Задача телеграфа, Odd Word problem и подобные очень легко решаются на короутинах. Без толковой поддержки в самом рантайме linq просто баловство, т.к. поток будет на каждый источник, комбинатор, транзитный и терминальный узлы. Т.е. одна строчка на linq в N комбинаторов породит 2N потоков, оптимизациями я пока не планирую заниматься, мне сейчас нужен как можно более чистый и читабельный код.
Здравствуйте, Tanker, Вы писали:
T>_next это следующая короутина.
Откуда корутина "знает", кто там следующий?
T>_input это вход, просто блокирующий ресурс. Для примера можно взять BlockingCollection<>, будет оно самое, только я написал свой, с целью разобраться с мониторами.
С мониторами всё не так, как с фиберами. Если чо. Использование потоков для корутин — это жуткий, чудовищный оверкилл.
S>>У меня складывается впечатление, что вы пытаетесь переизобрести RxLib, совместив IObservable и IEnumerable в вашем Co.
T>Короутины древнее не только IEnumerable, но всех дотнетов, виндовсов и линуксов вместе взятых. Так что скорее await и yield return выглядят попыткой изобрести короутины.
И тем не менее.
T>Скажем на короутинах эвенты и коллекции можно обрабатывать одним и тем же кодом. T>Кроме того, RX это реактивный код, а мне нужен императивный.
Вы что-то путаете. Императивный код — это IEnumerable, и он уже есть. Именно Rx потенциально позволяет обрабатывать евенты и коллекции одним и тем же кодом, т.к. содержит врапперы для превращения одного в другое.
T>Изоляция чисто для интелисенса, а то короутина поддерживает IEnumerable например.
S>>2. А чего так сложно-то? В оригинале мы имеем
T>Потому что это все таки эмуляция короутин, а не сами короутины. Я не в курсе всей математики короутин, потому не могу сказать, реализовал ли я общий случай, взяв за основу питоновские короутины.
Ну вот отсюда и мораль, что "эмуляция" выходит чудовищно дорогостоящей по ресурсам и многословной в синтаксисе.
T>В моем первом примере про генератор все это есть. Пока только короутина и генератор это разные классы, у меня тут хаос и шатание, три разных варианта пробую. Но вобще достаточно одного.
Скорее всего этот один вариант будет слишком тяжёлый. Но эксперименты — это интересно
Мне пока нравится идея Rx — в том смысле, что некоторый код удобнее писать в "активном" стиле, а некоторый — в "пассивном". "Пассивный" стиль — это всякие бесконтекстные штуки, типа "когда смениласьСистемнаяЦветоваяСхема -> ПерерисуйВсеОкна". Как только нужен контекст (скажем, детект дабл-клика), программирование в таком стиле превращается в адов кошмар. Я хочу иметь простой и понятный код, который описывает, как из потока кликов выделить дабл-клики, и простота и понятность требуют активного стиля. А сами дабл-клики — бесконтекстны, поэтому для их обработки я хочу писать в пассивном стиле.
Потому Rx выглядит сексуально — в нём оба стиля присутствуют, с возможностью явного переключения.
Побочный эффект — возможность писать "как бы активный" код, который на самом деле реактивный.
Единственное преимущество такого кода перед традиционным — низкое потребление ресурсов. Потому что если я хочу решить задачу "отпарсить HTTP-запрос по мере его прихода в сокет", то проще всего это сделать через blocking input.
Но это требует целого отдельного потока, который жрёт стек, но большую часть времени спит и затрудняет шедулинг.
IOCP гораздо эффективнее, но он требует пассивного стиля написания, что усложняет работу.
Хочу сразу всё — писать код парсинга в "активном стиле", но автоматически преобразовывать его в "реактивный" без отжирания ресурсов ОС.
Хочу иметь возможность так выворачивать не только работу с дискретными множествами (IEnumerable<T>), но и с потоками.
Потому что я хочу взять парсер XML, который имеет наглость активно читать из переданного ему StreamReader, в лучшем случае блокируя поток в ожидании инпута, и подсунуть к нему AntiStream, в который я буду пихать байты в удобном мне темпе.
T>С исключениями посложнее из за отдельного потока. Исключения буду делать по мере необходимости. Пока "я пейшу бес ашыбок".
Пока что я вижу сложности не в потоках, а в том, что у вас нет никакой семантики для Dispose.
T>Конечно. Но вообще говоря linq это не то, ради чего нужны короутины. Меня прежде всего интересует возможность делать энергичный императивный код ленивым.
Непонятно, как это будет работать с учётом единственности _next.
T>Да, библиотечка далека от завершения. Я на ней в основном проверяю кое какие идеи, это не продакшн код. Правда публиковать его не буду, хочу все таки опробовать в продакшне.
удачи. Да, не трогайте фиберы — вам не удастся их завести без манипуляций с CLR Host.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Tanker, Вы писали: T>Либа то не ради Linq2Co начиналась, Linq это побочный эффект. Задача телеграфа, Odd Word problem и подобные очень легко решаются на короутинах.
А можно привести сами задачи? А то мне кажется, что на Rx или Linq или async/await они решаются ещё легче.
T>Без толковой поддержки в самом рантайме linq просто баловство, т.к. поток будет на каждый источник, комбинатор, транзитный и терминальный узлы. Т.е. одна строчка на linq в N комбинаторов породит 2N потоков, оптимизациями я пока не планирую заниматься, мне сейчас нужен как можно более чистый и читабельный код.
Именно поэтому я и считаю решение на потоках с мониторами не более чем курьёзом.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
T>>Либа то не ради Linq2Co начиналась, Linq это побочный эффект. Задача телеграфа, Odd Word problem и подобные очень легко решаются на короутинах. S>А можно привести сами задачи? А то мне кажется, что на Rx или Linq или async/await они решаются ещё легче.
Здравствуйте, Sinclair, Вы писали:
T>>_next это следующая короутина. S>Откуда корутина "знает", кто там следующий?
Конвейер жостко связаный и мутабельный, по крайней мере в текущей реализации. Как сделать иммутабельный я пока что не пробовал.
S>Вы что-то путаете. Императивный код — это IEnumerable, и он уже есть. Именно Rx потенциально позволяет обрабатывать евенты и коллекции одним и тем же кодом, т.к. содержит врапперы для превращения одного в другое.
IEnumerable это pull. RX это push. Мне же надо сразу и то и другое.
S>Потому Rx выглядит сексуально — в нём оба стиля присутствуют, с возможностью явного переключения.
Вот это я не понял, поясни пожалуйста. Как детектить дабл клики я знаю. А что такое активный стиль в RX ?
S>Единственное преимущество такого кода перед традиционным — низкое потребление ресурсов. Потому что если я хочу решить задачу "отпарсить HTTP-запрос по мере его прихода в сокет", то проще всего это сделать через blocking input. S>Но это требует целого отдельного потока, который жрёт стек, но большую часть времени спит и затрудняет шедулинг.
blocking input нормально решается с короутинами. Шедулинг будет такой же как и с await.
S>IOCP гораздо эффективнее, но он требует пассивного стиля написания, что усложняет работу. S>Хочу сразу всё — писать код парсинга в "активном стиле", но автоматически преобразовывать его в "реактивный" без отжирания ресурсов ОС.
Это и есть короутины
T>>С исключениями посложнее из за отдельного потока. Исключения буду делать по мере необходимости. Пока "я пейшу бес ашыбок". S>Пока что я вижу сложности не в потоках, а в том, что у вас нет никакой семантики для Dispose.
Диспозить вобщем не проблема, но я это даже не начинал,
T>>Конечно. Но вообще говоря linq это не то, ради чего нужны короутины. Меня прежде всего интересует возможность делать энергичный императивный код ленивым. S>Непонятно, как это будет работать с учётом единственности _next.
По дефолту _next это короутина Fork. Собтсвенно из за этого и получается 2N потоков. Т.е. цепь может выглядет реально вот так
Здравствуйте, Tanker, Вы писали: T>Конвейер жостко связаный и мутабельный, по крайней мере в текущей реализации. Как сделать иммутабельный я пока что не пробовал.
Ок, понятно.
Имхо, вам стоит покопать в сторону Task<T>. Очень похожий функционал, плюс будете иметь синтаксическую поддержку в языке.
T>IEnumerable это pull. RX это push. Мне же надо сразу и то и другое.
IObservable и IEnumerable дуальны.
Вызываете IEnumerable.ToObservable() и получаете Push. Вызываете foreach(item in observable) — и получаете Pull. См. http://msdn.microsoft.com/en-us/library/hh211873(v=vs.103).aspx T>Вот это я не понял, поясни пожалуйста. Как детектить дабл клики я знаю. А что такое активный стиль в RX ?
Ну собственно это и есть активный стиль. Когда я пишу алгоритм над IObservable так, как будто это pull, пользуясь либо IEnumerable, либо Query Comprehension.
T>blocking input нормально решается с короутинами. Шедулинг будет такой же как и с await.
Ну то есть вы эмулируете await, только без синтаксической поддержки. Смысл неясен. Особенно пугают упоминания monitor.PulseAll и прочие прожорливые вещи.
T>Это и есть короутины
Корутины — это всего лишь один из способов представить требуемое. И не факт, что самый хороший. T>Диспозить вобщем не проблема, но я это даже не начинал,
Диспозить проблема в присутствии исключений. Почитайте блог Липперта на предмет особенностей обработки исключений в iterator block.
T>А можно даже завести цикл и получится один из вариантов рекурсии.
Интересно.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.