[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Lua 5.4 supports yield from __close, but fails with coroutine.close
- From: Jan Behrens <jbe-mlist@...>
- Date: Tue, 19 Sep 2023 13:43:41 +0200
On Tue, 19 Sep 2023 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