Para crear funciones generadoras, necesitamos que se implemente yield(value). Esto actuaría como yield(), pero el 'valor' se devolvería y se devolvería desde la llamada a resume().
Esto permitiría que range() se convierta en un iterador, en lugar de crear una matriz potencialmente enorme.
Esto también sería un paso hacia características agradables como la comprensión de listas/dicciones.
Solución desagradable:
func xrange(count, dict):
var i = 0
while i < count:
dict.next = i
yield()
i += 1
func do_stuff():
var curr = {}
var it = xrange(5, curr)
while curr.value != null:
print(curr.value)
it.resume()
Acabo de empezar a trabajar con Godot (me gusta hasta ahora) pero estoy de acuerdo en que siento que yield() debería poder devolver más que el estado de la función. El rendimiento es como regresar con la capacidad de reanudar (), por lo que la función debería poder "devolver" un valor al ceder.
Un posible enfoque en el que he estado pensando es aumentar [GDScript]FunctionState
(https://docs.godotengine.org/en/3.1/classes/class_gdscriptfunctionstate.html)
tener un método value() que devuelve el argumento a yield().
func co1():
yield(5)
s = co1()
print(s.value()) # prints 5
GDscript ya tiene un rendimiento que toma dos valores y espera una señal. Sin embargo, esta versión de un solo argumento solo devolvería su argumento en FunctionState. Con solo ese cambio, un generador podría escribirse como:
func xrange(count):
var i = 0
while i < count:
yield(i)
func do_stuff():
var it = xrange(5)
while it:
print(it.result())
it = it.resume()
Esto funciona bastante bien, pero hay una sutileza que vale la pena considerar. Cuando la función coroutine devuelve (en lugar de producir), se devuelve un valor, no un estado de función. En el ejemplo anterior, se devuelve nulo (porque la función es nula), que probamos para detener el bucle en do_stuff(). Si la función coroutine devuelve un valor [ej. imagine return false
al final de xrange()] entonces esa prueba se rompería.
Creo que le echaré un vistazo al código.
En mi opinión, el rendimiento (valor) sería, erm, valioso.
EDITAR: al observar el código, hay complicaciones con la versión de señal de yield, por lo que la sección que escribí a continuación se eliminó por ahora. Puede elaborar más tarde.
Hay algunos problemas sobre cómo funciona yield
, por lo que será reemplazado por await
que es más sencillo. Todavía no estoy seguro de si haremos generadores reales.
Si aún está interesado en la idea de agregar generadores, abra una nueva propuesta en el rastreador GIP siguiendo la plantilla de problema proporcionada (después de verificar que aún no existe). Puede hacer referencia a este problema y resumir las ideas en la propuesta. ¡Gracias por adelantado!
Comentario más útil
Acabo de empezar a trabajar con Godot (me gusta hasta ahora) pero estoy de acuerdo en que siento que yield() debería poder devolver más que el estado de la función. El rendimiento es como regresar con la capacidad de reanudar (), por lo que la función debería poder "devolver" un valor al ceder.
Un posible enfoque en el que he estado pensando es aumentar [GDScript]FunctionState
(https://docs.godotengine.org/en/3.1/classes/class_gdscriptfunctionstate.html)
tener un método value() que devuelve el argumento a yield().
GDscript ya tiene un rendimiento que toma dos valores y espera una señal. Sin embargo, esta versión de un solo argumento solo devolvería su argumento en FunctionState. Con solo ese cambio, un generador podría escribirse como:
Esto funciona bastante bien, pero hay una sutileza que vale la pena considerar. Cuando la función coroutine devuelve (en lugar de producir), se devuelve un valor, no un estado de función. En el ejemplo anterior, se devuelve nulo (porque la función es nula), que probamos para detener el bucle en do_stuff(). Si la función coroutine devuelve un valor [ej. imagine
return false
al final de xrange()] entonces esa prueba se rompería.Creo que le echaré un vistazo al código.
En mi opinión, el rendimiento (valor) sería, erm, valioso.
EDITAR: al observar el código, hay complicaciones con la versión de señal de yield, por lo que la sección que escribí a continuación se eliminó por ahora. Puede elaborar más tarde.