acquireX/releaseX maps nicely to lexical scope and adding a language feature to provide sugar for it is pretty nice, imo/e. Defer doesn't really "get it."
acquireX/releaseX maps nicely to lexical scope and adding a language feature to provide sugar for it is pretty nice, imo/e. Defer doesn't really "get it."
The core value prop of both “using” or “defer” is that a single scope can manage the lifetime of some resource while child scopes interact with that resource.
“Using” assumes that resource is a local object but that’s rarely actually the case - as in the example of a DB connection - it’s just how OOP represents it.
A good counter-example would be if I need to manage a resource via an API. Maybe one request creates the resource and another tears it down. (Eg, begin a transaction and then commit it). “Using requires me to implement a new class to represent this resource - that’s OOP at its finest - whereas “defer” allows just doing the thing (and works equally well for objects)
Just because it's on objects doesn't mean it's OOP.
Can you elaborate on this more? It would be hard to represent a DB connection without an object somewhere (or a closure that's effectively the same thing), and I don't understand how local or not comes into play.
> Using requires me to implement a new class to represent this resource
It just requires you to set a key. You could also have a function to add it or do it locally.
Locally setting up Symbol.dispose does require more boilerplate than `defer`. But if the dispose is built into the object then `using` is less boilerplate than `defer`. And if you use a function to add the disposal, `using` with an extra function call is also less boilerplate than `defer`.
logger.log("start")
defer logger.log("exit")
...
for keeping alive a reference (because you need to call C code) global.keepalive = myvar
defer global.keepalive = undefined
...
// call C code here
etcIf you have a one-off, defer is nicer looking but using is perfectly capable of doing the job:
function defer_it(callback) {
return { [Symbol.dispose]: callback };
}
// will look better with using void
using _ = defer_it(()=>logger.log("exit"));
Or use DisposableStack() as another comment in this thread mentions.