[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Yet another proposal for <toclose> (was Re: [ANN] Lua 5.4.0 (alpha) now available)
- From: Sergey Kovalev <kovserg33@...>
- Date: Fri, 28 Jun 2019 23:48:39 +0300
> Yes, I know, I should use the scope/auto INSIDE the coroutine. Or I
> have to put the last resume INSIDE scope. But the point is that with
> this implementation I can also mess around like in the example. With a
> real "Scoped annotation" like <toclose> I cannot.
I see no problem even in this case:
function scope(body)
local list,res={}
local function auto(close,msg)
return function(t)
if type(t)~='table' then error("need table: { expression }",2) end
if t[1] then table.insert(list,{ arg=t[1], fn=close or io.close })
else
if msg=='weak' then return table.unpack(t) end
error(msg or t[2] or "no resource",2)
end
return table.unpack(t)
end
end
local ok,err=pcall(function() res={body(auto)} end)
for i=#list,1,-1 do list[i].fn(list[i].arg) end
if not ok then
if type(err)~='string' then error(err,2)
else error("scope error\nlua: "..err,2) end
end
return table.unpack(res)
end
--------------------------------------------------------------------------------
local function my_open(...) print("open",...) return ... end
local function my_close(...) print("close",...) end
local a_coroutine = coroutine.create(function()
local auto = coroutine.yield() -- WTF? This beak normal logic. Just
use scope(function(auto) ... end) here
local f1 = auto(my_close){ my_open "file 1" }
coroutine.yield()
local f2 = auto(my_close){ my_open "file 2" }
coroutine.yield() -- here all files f1 and f2 are closed so you will
have error in case of real files
print("using", f1, "and", f2)
end)
coroutine.resume(a_coroutine)
print"-- scope.begin"
scope(function(auto)
coroutine.resume(a_coroutine, auto)
coroutine.resume(a_coroutine)
end)
print"-- scope.end"
coroutine.resume(a_coroutine)
The output:
-- scope.begin
open file 1
open file 2
close file 2
close file 1
-- scope.end
using file 1 and file 2
You use files after they have been closed. So you will have an error
in case of real files. Don't do like this.
Typical usage should look like this:
local a_coroutine = coroutine.create(function()
print"-- scope2.begin"
scope(function(auto)
local f1 = auto(my_close){ my_open "file 1" }
coroutine.yield()
local f2 = auto(my_close){ my_open "file 2" }
coroutine.yield()
print("using", f1, "and", f2)
end)
print"-- scope2.end"
end)
print"-- scope1.begin"
scope(function(auto)
local f0=auto(my_close){ my_open "file 0" }
coroutine.resume(a_coroutine)
coroutine.resume(a_coroutine)
end)
print"-- scope1.end"
coroutine.resume(a_coroutine)
It outputs:
-- scope1.begin
open file 0
-- scope2.begin
open file 1
open file 2
close file 0
-- scope1.end
using file 1 and file 2
close file 2
close file 1
-- scope2.end