有没有办法测试闭包是不是也是生成器?

Posted

技术标签:

【中文标题】有没有办法测试闭包是不是也是生成器?【英文标题】:Is there a way to test if a closure is also a generator?有没有办法测试闭包是否也是生成器? 【发布时间】:2014-09-28 11:26:37 【问题描述】:

我正在使用一个 php 类,它需要接受多种类型的迭代器并将它们包含在一个统一的包装器中。我需要支持(并且可以!)的一种迭代器类型是一个包含 yield 关键字的匿名函数——本质上是一个匿名生成器。

PHP 中有没有办法测试匿名函数是否是生成器?以下是我尝试过的方法列表(旨在显示输出,而不是我如何使用它们):

$anon = function()  yield 1; yield 2; ;   // build anonymous generator
gettype($anon);                             // "object"
$anon instanceof \Traversable;              // 0
$anon instanceof \Iterable;                 // 0
$anon instanceof \IteratorAggregate;        // 0
$anon instanceof \Generator;                // 0
$anon instanceof \Closure;                  // 1 -- but doesn't tell me whether or not the closure is actually generator

$anon = $anon();                            // invoke, then run the same checks
gettype($anon);                             // "object"
$anon instanceof \Traversable;              // 1 (!!!)
$anon instanceof \Iterable;                 // 0
$anon instanceof \IteratorAggregate;        // 0
$anon instanceof \Generator;                // 1 (!!!)
$anon instanceof \Closure;                  // 0

正如您在上面看到的,我可以调用匿名函数并然后确定该函数是否是可遍历类型,但是为了以延迟加载的方式实现这一点(例如,一个围绕 SQL 语句调用的匿名函数包装器,后跟每条记录的产量),我无法在 foreach 迭代之前调用匿名函数。

PHP 中是否有我遗漏的方法/类型可用于确定尚未调用 的匿名方法是否是生成器?

【问题讨论】:

【参考方案1】:

对于那些想知道的人,该匿名函数不是生成器。它返回 Generator 作为其调用的结果。

根据the docs:

第一次调用生成器函数时,会返回一个内部生成器类的对象。

【讨论】:

【参考方案2】:
$anon = function()  echo 'INVOKED', PHP_EOL; yield 1; yield 2; ;
$r = new ReflectionFunction($anon);
var_dump($r->isGenerator());

表演

bool(true);

INVOKED根本不显示,证明任何时候都没有调用闭包

【讨论】:

看起来很有希望!我猜 ReflectionFunction 构造函数不需要调用闭包来检索该信息? 不,reflectionFunction 根本不调用闭包

以上是关于有没有办法测试闭包是不是也是生成器?的主要内容,如果未能解决你的问题,请参考以下文章

Python--核心2(生成器,迭代器,闭包,装饰器)之生成器

Truffle - 有没有办法自动生成测试用例?

07 内部类闭包的变量是如何生成的?

07 内部类闭包的变量是如何生成的?

07 内部类闭包的变量是如何生成的?

python selenium-webdriver 生成测试报告 (十四)