如何在没有 foreach 的情况下使用 PHP 生成器?

2023-12-19

这是一个简单的 JavaScript 生成器(通过:http://blog.carbon Five.com/2013/12/01/hanging-up-on-callbacks-generators-in-ecmascript-6/ 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 中遇到了这个错误

致命错误:生成器无法使用“return”返回值

好的,那么也许我会使用另一个产量来获得最终值? ...

<?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" go?— 注意在 JS 示例中我能够访问"a""b"产生的值以及100最后结果。

  2. 发电机还没有完成!— 我得打电话send额外的时间来完成生成器

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

来自 PHP生成器::发送 http://php.net/manual/en/generator.send.php

public mixed Generator::send ( mixed $value )

将给定值作为当前结果发送到生成器yield表达式并恢复生成器的执行。

如果发电机不在yield表达式,当调用该方法时,会先让其前进到第一个yield发送值之前的表达式。因此,没有必要使用 PHP 生成器来“启动”生成器::下一个() http://php.net/manual/en/generator.next.php调用(就像在 Python 中完成的那样)。

强调“因此,没有必要使用 PHP 生成器来“启动”Generator::next()”。好吧,但这真正意味着什么?我不必像 JavaScript 示例那样“启动”它,但第一个产生的值也会被吞噬。

谁能解释一下你是如何逐步通过发电机的without用一个foreach?


第一个产生的值并没有被吞噬,只是你从来没有看过它。

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

然后您两次发送值并恢复执行,$g->valid() is 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 中你can 从发电机返回 https://wiki.php.net/rfc/generator-return-expressions.

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 - 发电机 http://www.php.net/manual/en/class.generator.php实施Iterator http://php.net/manual/en/class.iterator.php,所以它有适当的方法来处理它:current http://php.net/manual/en/generator.current.php, key http://php.net/manual/en/generator.key.php, next http://php.net/manual/en/generator.next.php, rewind http://php.net/manual/en/generator.rewind.php, and valid http://php.net/manual/en/generator.valid.php。需要注意的是rewind如果您在已经启动的生成器上调用它,将会抛出异常。

一个执行此操作并演示 PHP 7 新功能的示例生成器委托 https://wiki.php.net/rfc/generator-delegation:

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

$g = letterGenerator();

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

Output:

abcdefghijklmnopqrstuvwxyz
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在没有 foreach 的情况下使用 PHP 生成器? 的相关文章