Пилю full-blown coroutines и возник вопрос по дизайну метода Send, как его лучше оформить. Пример ниже
[TestMethod]
public void SimpleSend()
{
var resultIn = "";
var g = new Coroutine<string, string>(c =>
{
resultIn = c.yield("out");
});
var resultOut = g.Next(); // выполняет ровно до yield
g.Send("in"); // от c.yield и до конца
Assert.IsTrue(resultIn == "in" && resultOut == "out");
}
В данном случае после с.yield короутина заканчивается. Вопрос в том, как оформить это дело, варианты
1 Send возвращает null, а короутина устанавливает флажок IsExhausted
2 как в джаве и питоне, Send бросает исключаение StopIteration
3 вводится TrySend — отстой по моему, т.к. через него и придется работать
4 дополнительно к yield добавляется метод halt и его парамерт будет передаваться в Send + флажок IsExhausted. Проблема в том, что halt нельзя будет отличить от yield и это создает проблему с генераторами
5 еще что нибудь, не приходит в голову
Пример для halt:
[TestMethod]
public void SimpleSend()
{
var resultIn = "";
var g = new Coroutine<string, string>(c =>
{
resultIn = c.yield("out");
c.halt("finita"); // теоретически можно заменить на 'return "finita"'
});
var resultOut = g.Next(); // выполняет ровно до yield
var finita = g.Send("in"); // от yield и до конца
Assert.IsTrue(resultIn == "in" && resultOut == "out" && finita == "finita" && g.IsExhausted);
}
в генераторах нужно последний элемент выталкивать через halt, то есть
c.yield(1)
c.yield(2)
c.yield(3)
c.halt(4) // :wow: