|
Am 17.11.2015 um 15:01 schröbte Viacheslav Usov:
On Mon, Nov 16, 2015 at 6:28 PM, Philipp Janda <siffiejoe@gmx.net> wrote:What about: local t = transaction( function( a, b, c ) if c then c:destroy() end if b then b:clear() end if a then a:close() end end ) local a = t( f() ) local b = t( a:foo() ) local c = t( b:bar() ) -- do something with a, b, c -- ... t:commit() -- or t:rollback(), or t:cleanup() No locals declared before initialization, and you could provide a default rollback function that invokes `__gc` metamethods on all stored values (although I find that rather ugly and unsafe).I do not think I understand how that will work. I understand that the transaction thing, when initialized, gets a finalizer, which is a function of some arguments, and those arguments will be finalized. But how do you specify which argument is which?
Currently I use customized (x)pcall functions like you suggested instead of (or actually in addition to) finalizers. Each call to one of those functions creates a stack of transactions, and `transaction()` pushes a transaction object to the current stack. A transaction is just a simple array, so `t( f() )` will append the value returned by `f()` to the array. When an error occurs, or when `t:rollback()` or `t:cleanup()` is called, the elements are `unpack()`ed and passed to the cleanup function (so the order of the arguments and the `t()` calles must match). `t:commit()`/`t:rollback()` pop the transaction from the stack (if it's the most recent).
You can see the current state of my experiments here[1].
Cheers, V.
Philipp [1]: https://gist.github.com/siffiejoe/2c01b690bfdbc34b85a6