I am working with a PHP class which needs to accept multiple types of iterators and encompass them inside a unified wrapper. One of the types of iterators I need to support (and can!) is an anonymous function containing the yield keyword -- an anonymous generator, essentially.
Is there a way in PHP to test whether or not an anonymous function is a generator? The following is a list of methods I have tried (designed to show the outputs, not how I used them):
$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
As you can see above, I can invoke the anonymous function and then determine whether or not the function is a traversable type, but in order to implement this in a lazy-loading fashion (for example, an anonymous function wrapper around a SQL statement call followed by a yield of each record), I cannot invoke the anonymous function before the foreach iteration.
Are there any methods / types in PHP which I am missing that can be used to determine whether or not an anonymous method which has not yet been invoked is a generator?
$anon = function() { echo 'INVOKED', PHP_EOL; yield 1; yield 2; };
$r = new ReflectionFunction($anon);
var_dump($r->isGenerator());
shows
bool(true);
INVOKED
isn't displayed at all, proving that the closure isn't invoked at any time
For those who are wondering, that anonymous function is not a Generator. It returns Generator as result of its invocation.
According to the docs:
When a generator function is called for the first time, an object of the internal Generator class is returned.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With