Coroutine Communication in Lua

Jan 15, 2018 09:48 · 256 words · 2 minutes read Lua

In Lua we can yield back and forth to a running coroutine for communication. For example if we have a coroutine:

local function communication_example()
    local contents = coroutine.yield()
    print(contents)
    contents = coroutine.yield()
    print(contents)
end

We can operate it

local running = coroutine.create(communication_example)
coroutine.resume(running, 5)
coroutine.resume(running, 6)
coroutine.resume(running, 7)

However this code might not do exactly what you think. I misunderstood and thought this would print

5
6
7

But in actuality it prints

6
7

And the coroutine is not in the dead status which means it hasn’t been exhausted. It appears as if the coroutine just ignored the first argument which is surprising! Actually this is due to how coroutines are executed. Lets look at this line by line. When the first resume is called, it executes the function at the entry point:

coroutine.resume(running, 5) -> communication_example()

and proceeds to the first line where the coroutine yields back

local contents = coroutine.yield()

The coroutine gets resumed again and 6 is yielded in:

coroutine.resume(running, 6) ->
    local contents = coroutine.yield() # contents = 6
    print(contents)                    # 6

And then the same thing happens for 7. Since the function execution happens at the first resume, and the method takes no arguments and does nothing between execution and the first yield it makes sense that 5 would not be printed. So how can we get the expected behavior?

local function communication_example(contents)
    print(contents)
    contents = coroutine.yield()
    print(contents)
    contents = coroutine.yield()
    print(contents)
end

Which when executed with the same sample code as above prints what we expect

5
6
7