[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: clumsiness of pcall() syntax and how we deal with it
- From: Andrew Starks <andrew.starks@...>
- Date: Tue, 28 Apr 2015 10:33:20 -0500
On Tuesday, April 28, 2015, Thijs Schreijer <thijs@thijsschreijer.nl> wrote:
>
>
>
> > -----Original Message-----
> > From: lua-l-bounces@lists.lua.org [mailto:lua-l-bounces@lists.lua.org] On
> > Behalf Of Daniel Silverstone
> > Sent: dinsdag 28 april 2015 12:33
> > To: lua-l@lists.lua.org
> > Subject: Re: clumsiness of pcall() syntax and how we deal with it
> >
> > On Tue, Apr 28, 2015 at 13:19:04 +0300, Konstantin Osipov wrote:
> > > The first problem is in ambiguity of the second argument.
> > > In case there is no error, it's the return value of the function.
> > > Otherwise, it's a string with a message.
> >
> > I tend to use 'ok, result = pcall(xyz, blah)' and then:
> >
> > if ok then
> > ...use result as useful result...
> > else
> > ...result is the error...
> > end
> >
> > > How to name the second argument? And what if a function returns
> > > multiple arguments?
> >
> > Multiple returns is a toughie and I will admit I tend not to use
> > them in cases where I want to return errors too. Then again I tend
> > to code functions which return an ok, result tuple most of the time
> > and then deal with wrappering them in assert() when I'd rather they
> > threw an error.
> >
>
> After recently having worked on http clients (with copas/luasocket/luasec) I have started to appreciate the luasocket functions protect, try and newtry for error handling.
>
> Thijs
>
>
I'm processing media content in a graph and have the same need: a way
to roll back partial changes when an error is thrown in a node.
My model uses tables as objects and I've settled on wrapping xpcall like so:
do local xpcall = assert(xpcall)
function Resource:pcall(fun, ...)
return xpcall(fun, self.error_handler, self, ...)
end end
This is still a work in progress. I'm deciding whether or not I want
to have an 'on_error' function that wraps this one, so that a call
would look like this:
local result, result2, etc = self:on_error(function()
--clean up state here
end)
:pcall(self.method, arg1,arg2)
Right now, it works like pcall and I check the error after the
function call. If it fails, I clean up and error again, except my
error message is the error object that I got back from the prior
xpcall. I pre-pend the new stack info to the original error message
and the result is a pretty good idea of 'what happened'.
Also, I include the object's `name` field in the error message, which
has been surprisingly helpful when things are concurrent.
Through this process, I have learned:
1: I have much to learn about errors and how to handle them.
2: Good programs have good errors.
3: Post error cleanup is hard and it's probably a good idea to start
with the hardest part of that problem, first.
4: Lua's error handling facilities are actually pretty decent, as far
as my limited experience is able to discern. Whenever I have thought
that it was missing something, I realized that I could make it myself
or that I really didn't want it in the first place.
5: This topic can descend into a debate over opinions very quickly. I
like those, but others have a limited tolerance for them, most likely
because they've already debated the topic and settled it in their own
mind.
One final point @Konstantin: In Lua, meta-programming is normal. That
is, whatever it is that you want can be programmed into Lua and if it
cannot, then it's probably worth discussion. But if it can, I doubt
that it would get added. Too many people deal with errors in too many
different ways.
-Andrew