> Where using() runs the function in a coroutine and hooks errors in order to finalize the font.
This is very clever, but:
1. As already commented here, running the entire garbage collector, twice, is expensive.
2. It is fairly common, as in the LuaSQL example, that such scoped objects depend on each other. With C#'s using, one can write code such as
using (var a = f(), b = a.foo(), c = b.bar()) { ... }
The important part of that is that if, for example, foo() or bar() throws an exception, then everything in the parentheses that was instantiated before the exception will be finalized. With the proposed 'block' keyword, that would also be a natural outcome.
With your using() function, however, that is impossible to achieve. Even the basic part, a = f(), b = a:for(), c = b:bar() is already not expressible. But even if it were, somehow, then any error raised in foo() or bar() would not result in deterministic finalization. So with this approach, I essentially need to have a using() call per each object needing deterministic finalization, with a corresponding functional decomposition of my logic. Having to decompose my logic (and wrap parts of it in pcall calls) was the problem that I wanted to solve, so your approach does not really solve the problem. I find it much more natural and comprehensible to write
do
block a = f()
block b = a:foo()
block c = b:bar()
-- do something with a, b,c
end
rather than
using(
f(),
function(a)
using(
a:foo(),
function(b)
using(b:bar(),
function(c)
-- do something
end
)
end
)
end
)
(I hope the syntax above is well-formed; having to say this just stresses again why a better approach is needed)