php - tercera - ¿Hay alguna forma de probar si un cierre es también un generador?
generador enciende pero no genera electricidad (2)
Para aquellos que se preguntan, esa función anónima no es un generador. Devuelve Generador como resultado de su invocación.
Según los documentos :
Cuando se llama a una función de generador por primera vez, se devuelve un objeto de la clase Generador interna.
Estoy trabajando con una clase de PHP que necesita aceptar varios tipos de iteradores y abarcarlos dentro de un contenedor unificado. Uno de los tipos de iteradores que necesito admitir (y puedo) es una función anónima que contiene la palabra clave de rendimiento: un generador anónimo, esencialmente.
¿Hay alguna forma en PHP para probar si una función anónima es un generador o no? La siguiente es una lista de los métodos que he probado (diseñados para mostrar los resultados, no cómo los usé):
$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
Como puede ver arriba, puedo invocar la función anónima y luego determinar si la función es de tipo transitable, pero para implementarla de forma perezosa (por ejemplo, un envoltorio de función anónimo en torno a una llamada de sentencia SQL). seguido de un rendimiento de cada registro), no puedo invocar la función anónima antes de la iteración foreach.
¿Hay algún método / tipo en PHP que falte que pueda usarse para determinar si un método anónimo que aún no ha sido invocado es un generador?
$anon = function() { echo ''INVOKED'', PHP_EOL; yield 1; yield 2; };
$r = new ReflectionFunction($anon);
var_dump($r->isGenerator());
muestra
bool(true);
INVOKED
no se muestra en absoluto, lo que demuestra que el cierre no se invoca en ningún momento