[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: state of the Lua nation on resource cleanup
- From: Tommy Pettersson <ptp@...>
- Date: Sun, 25 Jan 2009 22:48:27 +0100
On Mon, Jan 19, 2009 at 06:37:35PM -0500, John Belmonte wrote:
> [1] Challenge: implement Alex Mania's "appendud" example function
> in plain Lua while keeping the code easy to follow. See
> <http://lua-users.org/lists/lua-l/2008-02/msg00243.html>.
If one doesn't care too much about syntactic sugar I think I can
come pretty close.
Well, there's an awful lot of apack/aunpack/pcall, so maybe not
super-easy to follow.
Btw, would it be cool with syntactic sugar for "application".
Something like apply@fun(a1, a2, ...) that just gets expanded to
apply(fun, a1, a2, ...). The idea is that a@b@c:d(x) is expand
to a@b@c.d(c, x) -> a@b(c.d, c, x) -> a(b, c.d, c, x). That
would make things like pcall@dofile(f), lazy@fib(n-1), and
finalize@tab:endupdate() much easier to read. And write. I often
write pcall(fun(a,b)) by mistake, but maybe that's just me.
-- pack and unpack argument lists
local function apack (...) return { n=select('#',...), ... } end
local function aunpack (a,i,j) j=j or a.n return unpack(a,i,j) end
-- protected scope with sequential finalizers
local function finalized (fun)
local pcall = pcall
return function (...) -- create wrapper
local finalizers = {}
local function add_finalizer (...)
finalizers[#finalizers+1] = apack(...)
end
local presult = apack( pcall( fun, add_finalizer, ... ))
local errors
for i = #finalizers, 1, -1 do
local ok, err = pcall( aunpack( finalizers[i] ))
if not ok then
if not errors then errors = {} end
table.insert( errors, 1, tostring(err) )
end
end
if not presult[1] then
-- preserve custom error type if possible
if not errors then error( presult[2], 0 ) end
table.insert( errors, 1, tostring(presult[2]) )
end
if errors then
error( table.concat(errors,'\n'), 0 )
else
return aunpack(presult, 2)
end
end
end
-- stubs
local tab = {
beginupdate = function (this) print('tab.beginupdate') end;
endupdate = function (this) print('tab.endupdate') end;
}
local ud = {
lock = function (this) print('ud.lock') end;
unlock = function (this) print('ud.unlock') end;
1,2,3,4,5;
}
-- here we go
appendud = finalized(function (fin, tab, ud)
tab:beginupdate() fin( tab.endupdate, tab )
ud:lock() fin( ud.unlock, ud )
for i = 1, #ud do
tab[#tab+1] = ud[i]
end
return 7, 17
end)
-- test
print( appendud( tab, ud ))
--
Tommy Pettersson <ptp@lysator.liu.se>