Question about coroutines in Lua. Why is xyz happening

This example is taken from this tutorial ( GitHub - ms-jpq/lua-async-await: Async Await in 90 lines of code. ) on how to
achieve async await pattern in Lua/Neovim.

My question: Why, when calling pong does x, y, and z get the return values and print values when they print nil in the second example where each resume is called separately.

I sort of understand that when they are called separately then the value doesn’t get stored in yield somehow, and in the recursive pong function then all calls are chained together and so it makes sense on some level, but I don’t feel like I understand this fully and it bugs me a lot.

What would be an elegant way of explaining the difference? :slight_smile:

local co = coroutine

local pong = function(thread)
  local nxt = nil
  nxt = function(cont, ...)
    -- print("cont:", cont, ...)
    if not cont then
      return ...
    else
      return nxt(co.resume(thread, ...))
    end
  end
  return nxt(co.resume(thread))
end

local function create_thread()
  return co.create(function()
    local x = co.yield(1)
    print("x:", x)
    local y, z = co.yield(2, 3)
    print("y, z:", y, z)
  end)
end

-- TEST A ----------
local thread = create_thread()

pong(thread)

-- OUTPUT:
-- x: 1
-- y, z: 2 3

-- TEST B ----------
local thread = create_thread()

co.resume(thread)
co.resume(thread)
co.resume(thread)
co.resume(thread)

-- OUTPUT:
-- x: nil
-- y, z: nil nil

This prints nils, because you are not sending anything to the thread object in resume calls:

main            thread
  │
  │  co.resume()
  └───────────────►┐
                   │
     co.yield(1)   │
  ┌◄───────────────┘
  │
  │  co.resume()
  └───────────────►┐
                   │local x = nil
     co.yield(2,3) │print("x: ", x)
  ┌◄───────────────┘
  │
  ▼                

Your first example, you are sending the printed values inside co.resume calls in your pongs (co.resume(thread, ...) ← the ellipsis is the varargs sent)