lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


David:

On Thu, Jun 20, 2019 at 1:19 PM David Heiko Kolf <david@dkolf.de> wrote:
> > 1. attempt to execute all the closing methods (as Lua-5.4.0 does now),
> > but report _the first encountered error_, instead of the last (in this
> > example, reporting the assert failure)
>
> In C# the last error is reported and I actually think that is the right
> decision.
> <https://stackoverflow.com/questions/2911215/what-happens-if-a-finally-block-throws-an-exception>

Just my two cents. I'm not a C# programmer, but this sounds similar to
Java finallys. If you make a "library class", like a file or socket,
and you provide a full-parameter closing method to be called in
finally, there is no problem in throwing, as finally is a block which
can have it's own exception handling. But, if you implement closeable
to use your object in a "try-with-resources", which I think is the
closest match to <toclose>, your exceptions are swallowed ( IIRC they
are stashed somewhere, but swallowed anyway ).

C++, allowing RAII, dows not need finally, but has a similar
"destructors do not throw mantra". And if you decide to build and use
any of the "finally" constructs, like the ones in the GSL, you can
have exception handling in them.

In both cases you normally use a similar strategy if you need it. You
have a full closing method, which may throw, and a potentially dumber
and safer no-throwing ( no erroring in the lua case ) one to be used
in the "autoclosing" paths, try-with-resources, C++ dtors, and, IMO,
lua's toclose.

IMO __close methods belong to resource/service objects, and it's no
throw behaviour can normally be unit tested on them, giving a way to
easily catch errors in them will lead to more difficult code in the
well written cases and, what is worst, send a message theat "throwing
in __close" is ok, and instigate people to write __close without care.


> Consider this program with two errors, where at least one is a
> programming mistake:
>   do
>     local z
>     local <toclose> resource = setmetatable({}, {
>       __close = function ()
>         z.closed = true -- error 2, z might be nil
>       end
>     })
>     error "something went wrong" -- error 1
>     z = {}
>   end
> If the first error is reported I will never even know that there was a
> second error. And once I fixed the first error, I probably won't see
> that there is problem with my __close function.
> However, if the last error is reported, I can fix that and after fixing
> it I will still see the first error.

That's true, but IMO a construct like that ( oportunistic closeing
code written in the same code chunk as the mian one ) would be better
served by one of the many ways you can simulate a try/finally.

Taking Java as a example again, as I do not do C#. If I got one thing
like this I use a try/finally. If I have a class with a common
finalization code which has to run a lot I wrap it in a Closeable,
unit test it to get sure close() is right and then use
try-with-resources.

Francisco Olarte.