我刚刚编写了一部分生成器,并且达到了正常运行的程度,但需要进行一些重构。该方法的结构如下:
public function getFlattenedList( array $elements ) {
foreach ( $elements as $element ) {
if ( $this->someCondition( $element ) ) {
// A pile of stuff here
if ( $anotherCondition ) {
for ( $i = 0; $i < $this->someValue(); $i++ ) {
yield $this->anotherOperation( $element );
}
}
}
else {
yield $this->someOperation( $element );
}
}
}
这种方法很大/很复杂。最明显的事情是将if分支的主体移出到自己的方法。像这样的东西
public function getFlattenedList( array $elements ) {
foreach ( $elements as $element ) {
if ( $this->someCondition( $element ) ) {
// ???
$this->getFlattenedElement( $element );
}
else {
yield $this->someOperation( $element );
}
}
}
private function getFlattenedElement() {
// A pile of stuff here
if ( $anotherCondition ) {
for ( $i = 0; $i < $this->someValue(); $i++ ) {
yield $this->anotherOperation( $element );
}
}
}
但是我当然不能只返回这个新函数的结果,因为它也是一个生成器。 (我希望它是一个生成器,所以只有在请求值时才能完成工作。)我做的工作是在if条件的主体内添加另一个循环:
public function getFlattenedList( array $elements ) {
foreach ( $elements as $element ) {
if ( $this->someCondition( $element ) ) {
foreach ( $this->getFlattenedElement( $element ) as $flattened ) {
yield $flattened;
}
}
else {
yield $this->someOperation( $element );
}
}
}
是否有可能避免必须添加该循环,同时保持生成器行为并很好地拆分方法?我之前没有使用过发电机,所以可能会遗漏一些明显的东西。
答案 0 :(得分:1)
您实际上要做的事情被称为生成器委派,现在它已成为PHP版本的问题。只有PHP版本7及更高版本支持生成器委派,它看起来像这样:
function gen_y() {
yield 1;
yield 2;
}
function gen_x() {
yield from gen_y();
yield from gen_y();
}
这将为您提供完全所需的效果或'递归'或'嵌套'或'委托'生成器调用。但现在的问题是PHP7。没有多少生产环境运行PHP7。为此,您需要编写另一个生成器,该生成器采用可生成生成器的生成器。像转换器一样。
我不会将代码粘贴到此处,但我最近遇到了这个问题,迫使我在PHP5中编写了一个包来做这个:hedronium/generator-nest
使用此包时,您只需生成生成器,并使用包提供的方法包装初始生成器调用。
use Hedronium\GeneratorNest\GeneratorNest;
function gen_x() {
yield gen_y();
yield gen_y();
}
foreach (GeneratorNest::nested(gen_x()) as $x) {
// Your Code.
}
我建议您查看来源,了解实际发生的情况。这是only 28 lines。;)