Как использовать PHP-генераторы без foreach?

Вот простой генератор JavaScript (через: http://blog.carbonfive.com/2013/12/01/hanging-up-on-callbacks-generators-in-ecmascript-6/)

function* powGenerator() {
var result = Math.pow(yield "a", yield "b");
return result;
}

var g = powGenerator();
console.log(g.next().value);   // "a", from the first yield
console.log(g.next(10).value); // "b", from the second
console.log(g.next(2).value);  // 100, the result

Я пытаюсь смоделировать что-то подобное с PHP, но это немного головная боль.

<?php
function powGenerator() {
return pow((yield 'a'), (yield 'b'));
}

Прежде чем идти дальше, я получаю эту ошибку в PHP

Неустранимая ошибка: генераторы не могут возвращать значения, используя «возврат»

Хорошо, возможно, я просто использую другую доходность, чтобы получить окончательное значение? …

<?php
function powGenerator() {
yield pow((yield 'a'), (yield 'b'));
}

$g = powGenerator(); //=> Generator {#180}
echo $g->send(10);   //=> "b"echo $g->send(2);    //=> 100

Итак, я вернул себе значение, но здесь есть две главные проблемы

  1. Где мой "a" идти? — Обратите внимание на пример JS, я смог получить доступ к обоим "a" и "b" дали значения, а также 100 конечный результат.

  2. Генератор еще не готов! — Я должен позвонить send дополнительное время для завершения генератора

    $g->valid();   //=> true
    $g->send('?'); //=> null
    $g->valid();   //=> false
    

Из PHP Генератор :: отправить

public mixed Generator::send ( mixed $value )

Посылает данное значение в генератор как результат тока yield Выражение и возобновляет выполнение генератора.

Если генератор не на yield Выражение, когда этот метод вызывается, он сначала будет позволено перейти к первому yield Выражение перед отправкой значения. Таким образом, нет необходимости «заправлять» генераторы PHP Генератор :: следующая () вызов (как это делается в Python).

Акцент на «как таковой» не обязательно «заправлять» генераторы PHP Generator::next()«Хорошо, но что это на самом деле означает? Мне не нужно« заправлять »это как пример JavaScript, но первое полученное значение также проглатывается.

Может кто-нибудь объяснить, как вы должны пройти через генераторы без используя foreach?

6

Решение

Первое полученное значение не было проглочено, вы просто никогда не смотрели на него.

$g = powGenerator();
echo $g->current(); //a

Затем вы дважды отправляете значения и возобновляете выполнение, $g->valid() является true после этого, потому что вы не возобновили после третьего yield — генератор не укомплектован и может быть что-то еще. Рассматривать:

function powGenerator() {
yield pow((yield 'a'), (yield 'b'));
echo "Okay, finishing here now!\n";
}

$g = powGenerator();
echo $g->current(), "\n"; //a
echo $g->send(10), "\n";  //b
echo $g->send(2), "\n";   //100
$g->next();               // Resumes execution of the generator,
// which prints its own message and completes.
var_dump($g->valid());    //false

Это выведет:

a
b
100
Okay, finishing here now!
bool(false)

Теперь в PHP 7 вы Можно возврат от генератора.

function powGenerator() {
return pow((yield 'a'), (yield 'b'));
echo "This will never print.";
}

$g = powGenerator();
echo $g->current(), "\n"; //a
echo $g->send(10), "\n";  //b
echo $g->send(2), "\n";   // Prints just the newline, you're moving on
// to a return which you must get explicitly.
var_dump($g->valid());    // Generator complete, you're free to get the return.
echo $g->getReturn(), "\n";

Какие выводы:

a
b

bool(false)
100

Что касается их прохождения без foreachГенератор инвентарь Итератор, так что у него есть подходящие методы, чтобы рассматривать его как таковой: ток, ключ, следующий, перемотка, а также действительный. С оговоркой, что rewind вызовет исключение, если вы вызовете его на генераторе, который уже начался.

Пример, который делает это, а также демонстрирует новый PHP 7 генерация делегирования:

function letterGenerator() {
yield from range('a', 'z');
}

$g = letterGenerator();

while ($g->valid()) {
echo $g->current();
$g->next();
}

Выход:

abcdefghijklmnopqrstuvwxyz
9

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]