K
K
Kirill Nesmeyanov2016-10-19 12:55:12
PHP
Kirill Nesmeyanov, 2016-10-19 12:55:12

How to work with coroutines for reading and writing at the same time?

Actually the subject, let's say we have a coroutine:

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

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

Returns a reference to the "items" iterator, but this one replaces them:
foreach ($items as &$item) {
  $item = yield;
}

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

When combined, we get something like this:
foreach ($items as &$item) {
    $item = (yield $item);
}

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

In the latter case, the iterations are shifted and instead of, say, 10 iterations, we get 5 with a step of 2. To fix this, you can use this option:
foreach ($items as &$item) {
    $item = yield (yield $item);
}

In this case, you can both "read" and "write", but this is only a crutch, because. it is impossible to miss the "tick" of the record, the current one will be duplicated.
You can try passing the generator by reference as an argument:
function myfoo(Generator $writer = null): Generator
{
    foreach ($items as &$item) { 
        yield $item;
        if ($writer !== null) {
            $item = $writer->current(); // $writer->next() ?
        }
    }
}

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

Something I can’t think of any universal solutions at all so that the function can be used both for reading and for reading + writing.
Any ideas? =)
UPD: I came up with this option:
foreach ($items as &$item) {
  $data = (yield $item);

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

But the problem is that it writes to the N+1 element, not the current one. Those. you can only insert into the data after the current tick, and not replace them, remaining on the current one =(
$i = 0;
foreach ($reader = myfoo() as $value) {
  echo ++$i . ') ' . $value . "\n";
  $reader->send($i);
}

As a result, we get something like:
1) 2
2) 3
3) 4
и т.д
.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
K
Kirill Nesmeyanov, 2016-10-19
@SerafimArts

Thanks everyone, issue resolved.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question