====== Introduction to Coroutines in Lua====== ===== Basics of Coroutines ===== ==== Creating a Coroutine: ==== A coroutine in Lua is created using the coroutine.create function, which takes a Lua function as an argument and returns a coroutine. function foo() print("Coroutine started") coroutine.yield() print("Coroutine resumed") end co = coroutine.create(foo) ===== Running a Coroutine: ===== To start or resume a coroutine, use coroutine.resume. This function runs the coroutine until it yields or terminates. coroutine.resume(co) -- Output: Coroutine started coroutine.resume(co) -- Output: Coroutine resumed ===== Yielding a Coroutine: ===== Within a coroutine, you can pause its execution using **coroutine.yield**. This allows the coroutine to yield control back to the caller, who can then resume it later. function bar() for i = 1, 3 do print("Iteration", i) coroutine.yield() end end co = coroutine.create(bar) for i = 1, 3 do coroutine.resume(co) -- Output: Iteration 1, Iteration 2, Iteration 3 end ===== Coroutine Status ===== You can check the status of a coroutine using **coroutine.status**. The possible statuses are: *** "running":** The coroutine is currently running. *** "suspended":** The coroutine is suspended and can be resumed. *** "normal":** The coroutine is active but not running (it has called yield). *** "dead":** The coroutine has finished its execution. print(coroutine.status(co)) -- Output: suspended (after first yield) coroutine.resume(co) print(coroutine.status(co)) -- Output: dead (after finishing) ===== Coroutine Functions ===== Lua provides several functions to work with coroutines: * **coroutine.create(f):** Creates a new coroutine with function **f**. * **coroutine.resume(co, ...):** Resumes the coroutine **co**, passing any arguments to it. * **coroutine.yield(...):** Yields the coroutine, optionally passing values back to the caller. * **coroutine.status(co):** Returns the status of the coroutine **co**. * ** coroutine.running():** Returns the currently running coroutine. ==== Example 1: Coroutine with Arguments ==== You can pass arguments to coroutines and use them within the coroutine function. function greet(name) print("Hello, " .. name) coroutine.yield() print("Goodbye, " .. name) end co = coroutine.create(greet) coroutine.resume(co, "Alice") -- Output: Hello, Alice coroutine.resume(co) -- Output: Goodbye, Alice ==== Example 2: Coroutine Communication ==== Coroutines can yield and return values to the caller. function add(a, b) coroutine.yield(a + b) end co = coroutine.create(add) success, result = coroutine.resume(co, 5, 7) -- Passes 5 and 7 to the coroutine print(result) -- Output: 12 ==== Example 3: Generating a Sequence with Coroutines ==== Coroutines can be used to generate sequences, such as the Fibonacci sequence. function fibonacci() local a, b = 0, 1 while true do coroutine.yield(a) a, b = b, a + b end end co = coroutine.create(fibonacci) for i = 1, 10 do success, value = coroutine.resume(co) print(value) -- Output: First 10 numbers of the Fibonacci sequence end ==== Example 4: Coroutine as a Producer-Consumer ==== Coroutines can be used to implement producer-consumer patterns. function producer() local i = 0 while true do i = i + 1 coroutine.yield(i) end end function consumer() while true do local status, value = coroutine.resume(pro) print("Consumed: " .. value) end end pro = coroutine.create(producer) consumer() -- This will consume and print the produced values indefinitely ====Example 5: Simple State Machine with Coroutines==== Coroutines can help in creating simple state machines. function state_a() print("In State A") coroutine.yield("go to B") print("Returning to State A") end function state_b() print("In State B") coroutine.yield("go to A") end state = {A = coroutine.create(state_a), B = coroutine.create(state_b)} current_state = "A" while true do local status, next_state = coroutine.resume(state[current_state]) if not status then break end current_state = (next_state == "go to A") and "A" or "B" end ==== Example 6: Round-Robin Scheduling ==== Coroutines can be used for round-robin scheduling to manage multiple tasks. function task1() for i = 1, 3 do print("Task 1, iteration " .. i) coroutine.yield() end end function task2() for i = 1, 3 do print("Task 2, iteration " .. i) coroutine.yield() end end tasks = {coroutine.create(task1), coroutine.create(task2)} while true do local all_done = true for i = 1, #tasks do if coroutine.status(tasks[i]) ~= "dead" then coroutine.resume(tasks[i]) all_done = false end end if all_done then break end end