SerafimArts
@SerafimArts
Senior Notepad Reader

Как работать с корутинами на чтение и запись одновременно?

Собственно сабж, допустим у нас есть корутинка:

foreach ($items as $item) {
    yield $item;
}

// foreach (myfoo() as  $item) ...


Возвращает ссылку на итератор "итемов", а вот такая подменяет их:

foreach ($items as &$item) {
  $item = yield;
}

// while ($iterator = myfoo()) { $iterator->send(23); }


Если совместить, получаем примерно такой вариант:

foreach ($items as &$item) {
    $item = (yield $item);
}

// while ($iterator = myfoo()) { $iterator->current() === 42 ?: $iterator->send(23); }


В последнем случае происходит сдвиг итераций и вместо, допустим, 10 итераций мы получаем 5 с шагом 2. Для исправления этого можно воспользоваться таким вариантом:

foreach ($items as &$item) {
    $item = yield (yield $item);
}


В этом случае можно и "читать" и "писать", но это лишь костыль, т.к. пропустить "тик" записи невозможно, произойдёт дублирование текущего.

Можно попробовать передать генератор по ссылке в качестве аргумента:

function myfoo(Generator $writer = null): Generator
{
    foreach ($items as &$item) { 
        yield $item;
        if ($writer !== null) {
            $item = $writer->current(); // $writer->next() ?
        }
    }
}

// myfoo(yield ээээээ.... А дальше что писать? На этом мои полномочия всё (с)


Что-то вообще не могу придумать никаких универсальных решений, чтобы функцию можно было использовать как на чтение, так и на чтение + запись.

Есть хоть какие-то идеи? =)

UPD: Придумался вот такой вариант:

foreach ($items as &$item) {
  $data = (yield $item);

  if ($data !== null) {
      $item = $data;
      yield $item;
  }
}


Но проблема в том, что он пишет в элемент N+1, а не текущий. Т.е. можно лишь внедряться в данные после текущего "тика", а не подменять их, оставаясь на текущем =(

$i = 0;
foreach ($reader = myfoo() as $value) {
  echo ++$i . ') ' . $value . "\n";
  $reader->send($i);
}


В результате получим что-то вроде:

1) 2
2) 3
3) 4
и т.д
.
  • Вопрос задан
  • 218 просмотров
Решения вопроса 1
SerafimArts
@SerafimArts Автор вопроса
Senior Notepad Reader
Всем спасибо, вопрос решён.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы