Resource management (eg. try-with-resources)
On Fri, Nov 10, 2017 at 3:00 PM, Michał Wadas <michalwadas at gmail.com> wrote:
After I started writing code extensively using async-await I have noticed that I would like to have automated way of dealing with resource management.
This is something I'd really like to see as well.
What's the motivation for having an open? Java's AutoCloseable just has
close; one would normally be acquiring these from a constructor or
function, which is effectively the open...?
Can you give a concrete example using the syntax you're looking at? E.g.,
were you really thinking of actually having with and as? If so, I'd
rather steal more directly from Java (perhaps replacing their ; with ,):
try (a = giveMeAResource(), b = giveMeAnotherResource()) {
// `a` and `b` are in scope here
} catch (e) {
// ...`a` and `b` are not in scope here
} finally {
// ...`a` and `b` are not in scope here
}
...where (off-the-cuff):
- Both
catchandfinallyare optional aandbare constants scoped to thetryblock (no need for the keyword, but could require or allow it for clarity)- Trailing commas on the resource declaration/initializer list are fine
b[Symbol.close]is called first, thena[Symbol.close]- Both
closes are called prior to the execution of code in thecatchorfinally(if any) - If the
tryblock throws, that error is the primary error and anyclosecalls that also throw are "suppressed errors" (more below) - If the
tryblock doesn't throw, but anyclosecalls do, the firstclosethat fails becomes the primary error; any others that fail become suppressed errors
Suppressed error handling:
- If the primary error is an
Errorobject, suppressed errors are added to asuppressedarray property on it (creating it if necessary) - If the primary error is not an
Errorobject, they're lost other than being treated as unhandled errors by the environment (for instance: logged, perhaps causing script termination; thought required on that)
-- T.J. Crowder
Here's a C++-inspired alternative:
let res = value[Symbol.resource]()- Get an optional promise to a resource. lf missing,resis set tovalueinstead.res[Symbol.close]()- Close a resource, optionally returning a promise.try let res = value- Get the resource by invokingvalue[Symbol.resource]()(or usingvalueif the method is missing), assign it tores, and invokeres[Symbol.resource]()once it leaves the scope, even on error.try await let res = value- Same as above, but awaitvalue[Symbol.resource]()(if necessary) andres[Symbol.close]()after calling them.try with expr,try await with expr- Same as above, but without declaring a binding. (Works well with transactions, locks, etc.)- Close exceptions replace thrown exceptions.
Benefits:
- Less nesting, more concise.
- Java's
try-with-resources is clunky and awkward. Python'swithstatement is no different. - It works well with sync and async resources.
- User-level primitives are easier to write.
Of course, in the spec, there's a few logical cases where you'd want these methods to be defined/used:
%IteratorPrototype%[@@close]()- returnthis.close()if such a method exists.%AsyncIteratorPrototype%[@@close]()- Similar to above.Atomics.lock(sab, index, size)- Return a resource that acquires a lock for this section, and releases on@@close.
After I started writing code extensively using async-await I have noticed that I would like to have automated way of dealing with resource management.
Scope-level manage was proven (Python, C++, Java at least) to be intuitive and error proof.
Previous discussion on this topic: esdiscuss. org/topic/resource-management
Example syntax:
try with Expression as Identifier {
} catch... finally...
Symbol.open and Symbol.close methods would be called respectively on entering and leaving try block.
Plays well with both synchronous and asynchronous resource access.
Another option is to reuse with:
with(expression as identifier) {
}
Though it would be confusing to statement with wildly different semantics in strict mode.
After I started writing code extensively using async-await I have noticed that I would like to have automated way of dealing with resource management. Scope-level manage was proven (Python, C++, Java at least) to be intuitive and error proof. Previous discussion on this topic: https://esdiscuss. org/topic/resource-management Example syntax: try with Expression as Identifier { } catch... finally... Symbol.open and Symbol.close methods would be called respectively on entering and leaving try block. Plays well with both synchronous and asynchronous resource access. Another option is to reuse with: with(expression as identifier) { } Though it would be confusing to statement with wildly different semantics in strict mode. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20171110/6acf4fe0/attachment.html>