[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Exceptions (was Re: Custom extensions to Lua)
- From: Rici Lake <lua@...>
- Date: Fri, 12 Aug 2005 14:24:50 -0500
On 12-Aug-05, at 8:08 AM, Roberto Ierusalimschy wrote:
I still think that we can do that with finalizers. As long as each
object has a proper finalizer (i.e., a __gc metamethod), all we have to
do in case of errors is to call collectgarbage() to finalize what was
left.
There are lots of things that can be done with gc finalizers, but I
think they fall into a different category than the things that maybe
should be done with cleanup clauses.
A gc finalizer is good for deallocation of resources, but it doesn't
solve the problem of maintaining state which is aligned with the
dynamic execution state.
To be slightly less theoretical :), Lua's io library still contains the
io.input and io.output methods, which could be quite handy for
temporarily diverting input and output:
function with_output(f, func, ...)
local out = io.output()
io.output(f)
func(...)
io.output(out)
end
This suffers from two problems: first, it will fail if func throws an
error, and second, I'm tossing away func's return value(s).
I can fix the first problem by pcall'ing func, but I might be reluctant
to do that for a couple of reasons: (1) pcall'ing defeats yield(), (2)
I would then end up having captured an error I'm not interested in.
Similarly, I can fix the second problem by keeping some number of
return values (probably 1) or using some complicated mechanism for
keeping a vector of return values and then saving them.
So I might end up with something like this (which also has some flaws):
function capture(flag, ...)
-- unpredictable results if ... contains a nil
if flag then return flag, {...}
else return flag, (...)
end
end
function with_output(f, ...)
local out = io.output()
io.output(f)
local flag, rv = capture(pcall(...))
io.output(out)
if flag then return unpack(rv)
else error(rv, 0)
end
end
Contrast with:
function with_output(f, func, ...)
local out = io.output()
return block (ret)
ret(func(...))
finally
io.output(out)
end
end
Provided the compiler were clever enough to not use TAILCALL inside a
block, this could be written:
function with_output(f, func, ...)
local out = io.output()
block()
return func(...)
finally
io.output(out)
end
end