lua-async-await
lua-async-await copied to clipboard
Use tail calls where applicable
Lua specifies tail calls as part of the language, which can be taken advantage of in the code presented.
However, having function A calling function, B right at the end, like the following is not enough.
function B() dosomething() end
function A()
B()
end
This is because lua doesn't know how many items function B will return and has to clean the lua stack up in case function B returns anything, because A is not supposed to return anything itself. This means that the last thing function A does is clean up the lua stack after B returns, not calling function B itself. Because of this, the tail call optimization cannot be applied.
However in the following similar snippet:
function B() dosomething() end
function A()
return B()
end
Here, since function A returns exactly the same thing as function B, the last thing function A does really is calling function B (because after B returns, the lua stack will contain exactly what A needs to immediately return). So in this case, the call to B will be tail-call optimized and no extra stack space is used.
An example of where this optimization can be used (because we don't really care what the relevant functions return) is in the step function within the pong function, for example:
step = function(...)
local stat, ret = coroutine.resume(thread, ...)
assert(stat, ret)
if coroutine.status(thread) == 'dead' then
return (callback or function() end)(ret)
else
assert(type(ret) == 'function', 'type error :: expected func')
return ret(step)
end
end
and in the callback inside the join
function:
local callback = function(...)
acc[i] = { ... }
done = done + 1
if done == len then
return step(unpack(acc))
end
end