gpt4 book ai didi

php - 将 "yield from"与迭代器或生成器一起使用时的行为差异

转载 作者:行者123 更新时间:2023-12-04 01:49:27 24 4
gpt4 key购买 nike

根据documentation如果可能的话,它会委托(delegate)任何 Traversable 对象的生成。但是,我看到了 yield from {a Generator instance}yield from {an Iterator instance} 之间的区别。

一个例子。

这段代码有一个 Iterator 和一个 Generator 做同样的事情:它们提供“1, 2, 3”序列:

$iterator = new class implements \Iterator {

private $values = [1, 2, 3];

public function current()
{
return current($this->values);
}

public function next()
{
next($this->values);
}

public function key()
{
return key(this->values);
}

public function valid()
{
return current($this->values) !== false;
}

public function rewind()
{
reset($this->values);
}
};

$generator = (function ()
{
yield 1;
yield 2;
yield 3;
})();

但是当我尝试从它们yield from 时,我得到了不同的结果。让我们来玩一下这个函数:

function skipOne(\Iterator $iterator)
{
$iterator->next();
yield from $iterator;
}

有了生成器,一切都按预期工作:

foreach (skipOne($generator) as $value) {
var_dump($value);
}

Output:
int(2)
int(3)

但是对于迭代器,它不会跳过第一个数字:

foreach (skipOne($iterator) as $value) {
var_dump($value);
}

Output:
int(1)
int(2)
int(3)

我发现 yield from 运算符由于某种原因导致 $iterator->rewind() 调用。我做错了什么?

最佳答案

你没有做任何的事。

yield from 将尝试倒带 能够倒带的东西,但生成器不能,它们只会向前。

这就是您的代码在第一个示例中按预期运行的原因,而不是在第二个示例中。

您可以将 $iterator 包装在生成器中,您会得到相同的结果。

$wrappedIterator = (function($iterator) {
foreach ($iterator as $value) {
yield $value;
}
})($iterator);

您只是利用了发电机一次性使用的“优势”,因为它们只能前进而永远不会倒转。

例如,foreach 也会发生同样的情况,因为它还会尝试倒回正在循环的内容。

如果你只是做了

$iterator->next();
foreach ($iterator as $value) {
var_dump($value);
}

你还会得到:

int(1)

int(2)

int(3)

在这两种情况下(yield fromforeach)迭代器都将被倒带。

如果你尝试过

$generator->next();
foreach ($generator as $value) {
var_dump($value);
}

你会得到一个 fatal error 。

在您的情况下,由于当 yield from 无法倒带其影响的对象时,它不会提示并继续进行,就好像什么都没发生一样,这可能会造成混淆。

您可以通过检查 this 轻松验证行为.

关于php - 将 "yield from"与迭代器或生成器一起使用时的行为差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53939816/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com