You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The call to finally is required. When called, finally first calls the function from try in a coroutine, then if that coroutine yields an IOException in a specific way, it calls the function from catch, or if another type of exception is yielded, it yields to the parent try-catch, and so on. Either way, it calls finally after exiting the try, and automatically closes any associated resources (which need to be wrapped with file() or closeable() or some other wrapper, since you can't shove varargs/varrets in the middle of the args list and stuff).
Why you need coroutines: pcall and error without pcall and error.
So, let's take Lua, remove pcall and error, and tweak coroutines a bit:
-- NOTE: THIS IMPLEMENTATION IS UNTESTED AND MAY CONTAIN BUGS.-- get rid of native pcall and errorpcall=nilerror=nil-- we're gonna wrap coroutines, so this is importantlocalcocreate, coresume, costatus, corunning=coroutine.create, coroutine.resume, coroutine.status, coroutine.runninglocalisdead= {}
setmetatable(isdead, {__mode="k"})
-- reimplement coroutine.resumecoroutine.resume=function(...)
return (function(ok, ...) ifokthenreturn...elsereturnok, ...endend)(coresume(...))
end-- reimplement coroutine.yieldcoroutine.yield=function(...)
returncoyield(true, ...)
end-- reimplement coroutine.statuscoroutine.status=function(co)
ifisdead[co] thenreturn"dead" elsereturncostatus(co) endend-- reimplement coroutine.wrapcoroutine.wrap=function(f)
localco=cocreate(f)
returnfunction(...)
return (function(...)
if...thenreturnselect(2, ...)
else-- note: using global. will be redefined below.error((select(2, ...)))
endend)(coroutine.resume(co)) -- note that we replaced coroutine.resume aboveendend-- reimplement error on top of coroutineserror=function(msg, level)
isdead[corunning()] =truecoyield(false, msg, levelor1) -- uses raw/internal coyield, not the wrapper we created abovewhiletruedocoyield(false, "attempt to resume a dead coroutine") endend-- reimplement pcall on top of coroutinespcall=function(f, ...)
localco=cocreate(f)
localfunctionrecurse2(recurse, ...)
returnrecurse(coroutine.resume(co, ...))
endlocalfunctionrecurse(ok, ...)
ifcoroutine.status(co) =="dead" thenreturnok, ...elsereturnrecurse2(recurse, coroutine.yield(...))
endendreturnrecurse2(recurse, ...)
end-- xpcall is similar, except the error handler needs to be called by error().
And now we have pcall and error implemented on top of coroutines (a "high-level" pcall and error).