Skip to content

Instantly share code, notes, and snippets.

@takase1121
Created March 13, 2023 12:25
Show Gist options
  • Save takase1121/f75a3e56f807b784b695556558eb0e97 to your computer and use it in GitHub Desktop.
Save takase1121/f75a3e56f807b784b695556558eb0e97 to your computer and use it in GitHub Desktop.
Simple callback to coroutine function.
---Converts a function with callback into coroutine-style wait.
---This function accepts a function which a "resolver" function
---is passed as the only argument.
---When this "resolver" function is called, control is yielded
---back to the user.
---@param fn fun(...: any): ...any
---@returns ...any
local function await(fn)
local co = coroutine.running()
local ret
-- call the function with the resolver.
-- if it is resolved immediately, simply return the results.
-- Otherwise, execution will be stopped with coroutine.yield
-- and the resolver will resume the coroutine with our results
-- at a later time.
fn(function(...)
if coroutine.status(co) == "running" then
ret = table.pack(...)
else
return coroutine.resume(co, ...)
end
end)
if ret then
return table.unpack(ret, 1, ret.n)
else
return coroutine.yield()
end
end
---Await for a function that accepts callbacks.
---@param fn fun(...: any, cb: fun(...: any): nil): nil the function to call
---@returns any...
local function await_cb(fn, ...)
local arg = { ... }
return await(function(res)
arg[#arg + 1] = res
---@diagnostic disable-next-line: missing-parameter
fn(table.unpack(arg))
end)
end
---Creates a coroutine and runs it immediately.
---Use this in conjunction with await.
---@param fn fun(): nil the function to execute
---@returns any... the return value of the coroutine
local function async(fn) return coroutine.wrap(fn)() end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment