有没有办法测试闭包是不是也是生成器?
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 根本不调用闭包以上是关于有没有办法测试闭包是不是也是生成器?的主要内容,如果未能解决你的问题,请参考以下文章