lua-users home
lua-l archive

Re: Lua 5.4 supports yield from __close, but fails with coroutine.close

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On 2023年9月19日 10:24:07 +0100
Marcus Mason <m4gicks@gmail.com> wrote:
> >Use case is implementing something like an effect system for Lua, see
> ><https://koka-lang.github.io/koka/doc/book.html> where causing an
> >effect is implemented by yielding in Lua.
> 
> The general pattern I think for this is to yield a tagged value to request
> an effect be performed. You might expose a function called "perform(...)"
> which performs such a yield. You can then implement a closer in terms of
> this higher level function and it should just work: tm:
My current solution is to not use "coroutine.close" but instead do
"coroutine.resume(early_return)" to close the coroutine. In this
context, "early_return" is a special marker that causes a "perform"
function, which you mentioned, to initiate a stack unwinding by invoking
"error(early_return)".
local function catch_early_return(...)
 if ... == early_return then
 error(early_return)
 else
 return ...
 end
end
function perform(...)
 return catch_early_return(coroutine.yield(...))
end
See also attached "cantyield2.lua" file, which solves the issue (but
requires resuming the coroutine during the cleanup process, as Gé
Weijers already suggested).
So instead of calling "coroutine.close", I do a
"coroutine.resume(early_return)".
Inside the coroutine, I use an "xpcall" to ensure that the coroutine's
stack is unwound on errors (including the "early return" error), such
that all __close metamethods run without needing to use
"coroutine.close".
A tricky issue is to keep track of all involved call stacks for
debugging purposes (including nested coroutines), which is what I'm
still working on.
Regards,
Jan

Attachment: cantyield2.lua
Description: Binary data


AltStyle によって変換されたページ (->オリジナル) /