Buscar..
Sintaxis
coroutine.create (function) devuelve una coroutine (type (coroutine) == 'thread') que contiene la función.
coroutine.resume (co, ...) reanudar, o iniciar la coroutine. Cualquier argumento adicional dado para reanudar se devuelve desde coroutine.yield () que previamente pausó la coroutine. Si no se ha iniciado la rutina, los argumentos adicionales se convierten en los argumentos de la función.
coroutine.yield (...) produce la coroutine actualmente en ejecución. La ejecución se recupera después de la llamada a coroutine.resume () que inició esa coroutine. Cualquier argumento dado para ceder se devuelve del coroutine.resume () correspondiente que inició la coroutine.
coroutine.status (co) devuelve el estado de la coroutine, que puede ser:
- "muerto": la función en la coroutine ha llegado a su fin y la coroutine ya no se puede reanudar.
- "running": el coroutine se ha reanudado y se está ejecutando
- "normal": la coroutine ha reanudado otra coroutine.
- "suspendido": la corutina ha cedido, y está esperando para ser reanudada
coroutine.wrap (función) devuelve una función que, cuando se le llama, reanuda la coroutina que habría sido creada por coroutine.create (función).
Observaciones
El sistema coroutine ha sido implementado en lua para emular multiproceso existente en otros idiomas. Funciona cambiando a una velocidad extremadamente alta entre diferentes funciones para que el usuario humano piense que se ejecutan al mismo tiempo.
Crea y utiliza una coroutina.
Todas las funciones para interactuar con coroutines están disponibles en la tabla de coroutine . Se crea una nueva coroutine usando la función coroutine.create con un solo argumento: una función con el código a ejecutar:
thread1 = coroutine.create(function()
print("honk")
end)
print(thread1)
-->> thread: 6b028b8c
Un objeto de coroutine devuelve el valor del tipo thread , que representa una nueva coroutine. Cuando se crea una nueva coroutine, su estado inicial se suspende:
print(coroutine.status(thread1))
-->> suspended
Para reanudar o iniciar una rutina, se utiliza la función coroutine.resume , el primer argumento dado es el objeto de hilo:
coroutine.resume(thread1)
-->> honk
Ahora el coroutine ejecuta el código y termina, cambiando su estado a muerto , que no se puede reanudar.
print(coroutine.status(thread1))
-->> dead
Coroutines puede suspender su ejecución y reanudarla más tarde gracias a la función coroutine.yield :
thread2 = coroutine.create(function()
for n = 1, 5 do
print("honk "..n)
coroutine.yield()
end
end)
Como puede ver, coroutine.yield () está presente dentro del bucle for, ahora, cuando reanudamos la coroutine, ejecutará el código hasta que alcance un coroutine.yield:
coroutine.resume(thread2)
-->> honk 1
coroutine.resume(thread2)
-->> honk 2
Después de terminar el bucle, el estado del hilo se convierte en muerto y no se puede reanudar. Coroutines también permite el intercambio entre datos:
thread3 = coroutine.create(function(complement)
print("honk "..complement)
coroutine.yield()
print("honk again "..complement)
end)
coroutine.resume(thread3, "stackoverflow")
-->> honk stackoverflow
Si la rutina se ejecuta de nuevo sin argumentos adicionales, el complemento seguirá siendo el argumento de la primera reanudación, en este caso "stackoverflow":
coroutine.resume(thread3)
-->> honk again stackoverflow
Finalmente, cuando finaliza una rutina, cualquier valor devuelto por su función va al currículum correspondiente:
thread4 = coroutine.create(function(a, b)
local c = a+b
coroutine.yield()
return c
end)
coroutine.resume(thread4, 1, 2)
print(coroutine.resume(thread4))
-->> true, 3
En esta función, se utilizan Coroutines para devolver los valores a un hilo de llamada desde lo profundo de una llamada recursiva.
local function Combinations(l, r)
local ll = #l
r = r or ll
local sel = {}
local function rhelper(depth, last)
depth = depth or 1
last = last or 1
if depth > r then
coroutine.yield(sel)
else
for i = last, ll - (r - depth) do
sel[depth] = l[i]
rhelper(depth+1, i+1)
end
end
end
return coroutine.wrap(rhelper)
end
for v in Combinations({1, 2, 3}, 2) do
print("{"..table.concat(v, ", ").."}")
end
--> {1, 2}
--> {1, 3}
--> {2, 3}
Coroutines también se puede utilizar para la evaluación perezosa.
-- slices a generator 'c' taking every 'step'th output from the generator
-- starting at the 'start'th output to the 'stop'th output
function slice(c, start, step, stop)
local _
return coroutine.wrap(function()
for i = 1, start-1 do
_ = c()
end
for i = start, stop do
if (i - start) % step == 0 then
coroutine.yield(c())
else
_ = c()
end
end
end)
end
local alphabet = {}
for c = string.byte('a'), string.byte('z') do
alphabet[#alphabet+1] = string.char(c)
end
-- only yields combinations 100 through 102
-- requires evaluating the first 100 combinations, but not the next 5311633
local s = slice(Combinations(alphabet, 10), 100, 1, 102)
for i in s do
print(table.concat(i))
end
--> abcdefghpr
--> abcdefghps
--> abcdefghpt
Coroutines se puede usar para construcciones de tuberías como se describe en Programming In Lua . El autor de PiL, Roberto Ierusalimschy, también ha publicado un artículo sobre el uso de las coroutinas para implementar mecanismos de control de flujo más avanzados y generales, como las continuaciones.