Подтвердить что ты не робот

Есть ли способ проверить, является ли закрытие также генератором?

Я работаю с классом 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, которые отсутствуют, которые могут использоваться для определения того, является ли анонимный метод, который еще не был вызван, является генератором?

4b9b3361

Ответ 1

$anon = function() { echo 'INVOKED', PHP_EOL; yield 1; yield 2; };
$r = new ReflectionFunction($anon);
var_dump($r->isGenerator());

показывает

bool(true);

INVOKED вообще не отображается, доказывая, что закрытие не вызывается в любое время

Ответ 2

Для тех, кто задается вопросом, что анонимная функция не является генератором. Он возвращает генератор в результате его вызова.

Согласно документы:

Когда функция генератора вызывается в первый раз, возвращается объект внутреннего класса Generator.