| Summary: | [xtend] Support for try-with-resource | ||
|---|---|---|---|
| Product: | [Tools] Xtend | Reporter: | Sebastian Zarnekow <sebastian.zarnekow> |
| Component: | Core | Assignee: | Project Inbox <xtend-inbox> |
| Status: | CLOSED FIXED | QA Contact: | |
| Severity: | enhancement | ||
| Priority: | P3 | CC: | btickets, christian.dietrich.opensource, eclipse, info, joerg83reichert, lieven.lemiengre, lorenzo.bettini, max.bureck, moritz.eysholdt, st.oehme, sven.efftinge, tom.schindl |
| Version: | 2.2.0 | ||
| Target Milestone: | --- | ||
| Hardware: | All | ||
| OS: | All | ||
| Whiteboard: | v2.18 | ||
| Bug Depends on: | |||
| Bug Blocks: | 457593 | ||
Alternatively we could introduce a library function taking a Closable or Autoclosable and a block: tryWith(new FileOutputStream(someFile)) [ // do stuff with it ] Maybe with one (or two) overloaded variant for two (or three) closables. Having overloaded variants may lead to unclosed resources if we implement this as a library function:
tryWith(new FileOutputStream(fileA), new FileOutputStream(fileB)) [ .. ]
Assuming the second output stream cannot be created and the constructor throws an IOException, the first one will never be closed. That's why I favored the compilation to a real try .. finally instead of the library approach.
try(stream = new FileOutputStream(someFile)) {
}
could be compiled to
FileOutputStream stream = null;
try {
stream = new FileOutputStream();
} finally {
if (stream != null) {
try { stream.close();
} catch(IOException e) { .. }
}
}
This pattern could be applied to more than one closable in the try(..) part.
I see. What if we pass in providers: tryWith( streamOne(), [streamTwo()]) [ a, b | // do stuff with a and b ] It's admittedly isn't a totally nice syntax, but it's library and not a language feature, which is a huge plus IMHO. Since the provider for the second closable does not take any arguments, the syntax would be even worse:
tryWith( streamOne(), [|streamTwo()]) [
a, b |
// do stuff with a and b
]
Furthermore anything that is used by the constructor of streamTwo has to be final in the method body. Therefore I think it would be ok to use nested tryWith invocations for the rare case of having two closables at hand
tryWith(streamOne()) [ first |
tryWith(streamTwo()) [ second |
.. do the hard work here
]
]
Since we have sneaky throw for Xtend, it should work well enough:
try {
tryWith(newStream()) [ // this save the finally dance in the surrounding try
]
} catch(IOException e) {
// alert, log, do whatever you like
}
and it's not too bad compared to a first class support for new instances as 'argument' for the try block:
try(newStream()) {
// hardwork with 'it'
} catch(IOException ioe) {
// logging
}
(In reply to comment #4) > Since the provider for the second closable does not take any arguments, the > syntax would be even worse: > > tryWith( streamOne(), [|streamTwo()]) [ > a, b | > // do stuff with a and b > ] That depends on how we define the signature ;-) > > Furthermore anything that is used by the constructor of streamTwo has to be > final in the method body. Since final is the default in Xtend anyway I don't consider this a problem. > Therefore I think it would be ok to use nested > tryWith invocations for the rare case of having two closables at hand > > tryWith(streamOne()) [ first | > tryWith(streamTwo()) [ second | > .. do the hard work here > ] > ] Looks good and is even simpler. :-) Alternativly we could make this an implicit extension method instead of a tryWith(..) routine: new FileOutputStream(..).closeAfter [ // do something with *it* ] It would probably need a better name, though. Yes, that's nice and I also like the name. Alternatively we could use one of the operators, e.g new FileInputStream(myFile) => [ processStuff() ] or new Reader(..) >>> [ ] We just talked about this some more and decided that we should go with the language feature instead of the library method, because: 1. The syntax gets awkward for more than one closable 2. Having more than one closable is pretty common (OutputStream => OutputStreamWriter => BufferdWriter) 3. The AutoClosable interface was only introduced in Java 1.7 +1 .. just found this, would be nice to have this now? In the mean time, https://github.com/dslmeinte/Xtend-utils/blob/master/Xtend-util/src/nl/dslmeinte/xtend/resources/ResourcesUtil.xtend looks neat. I implemented try-with-resources in Jbase (https://github.com/LorenzoBettini/jbase/pull/60). If there's still interest in supporting try-with-resources in Xbase I can work on that (hopefully, it should be rather straightforward now that I know where to put my hands on :) > If there's still interest in supporting try-with-resources in Xbase
Hi Lorenzo, FYI I personally currently use Xtend less than I used to when writing the comment above - but generally speaking the feature still seems like a nice to have...
I often miss this feature... The GitHub issue is closed (https://github.com/eclipse/xtext-xtend/issues/395), I am simply closing this bug accordingly, if you don't mind 😀 |
try(stream = new FileOutputStream(someFile)) { // do things with stream } We should consider this for Closables and AutoCloseables (on the contrary to Java) and always compile to try { } finally { } with a reasonable idiom in the finally block.