Thanks for the reply. So if I use an AutoCloseable, I would have something
like:
class Foo {
private state
def bar() {
def temp = state
state = newState
try ({ -> state = temp } as AutoCloseable) { // or rewrite this line using
withCloseable
baz()
}
}
}
In my case, Foo is something that visits the elements of a tree or list. I
don't want to create a new instance to visit each element. bar represents a
method that advances to the next element and baz (maybe from super type)
processes the next element set in "state". state is a field or property so I
am expecting the assignments to live inside the bar method's scope.
My goal is to eliminate repetitious typing of assigning the current value to a
temporary variable, assigning the next value to the field and at the end
restoring the previous value.
From: Leo Gertsenshteyn <[email protected]>
Sent: Saturday, November 21, 2020 5:34 PM
To: [email protected]
Subject: Re: Alternatives to try/finally code structure
Hi Eric,
Am I correctly interpreting that baz() in the above examples calls into 3rd
party code and that code has direct reference to the state and controls the
state variables' lifecycle? If that's not the case, there may much much simpler
solutions involving intermediate objects, recursion, etc., but I will assume
those are not available to you.
In that case, these look like scenarios for which Java's "try-with-resources"
was meant to reduce verbosity. It allows a try block to take objects that
implement the AutoCloseable interface and it will call their "close()" methods
at the end of the block -- no "finally" needed.
In Groovy, we can leverage that with ".withCloseable { ... }" closure blocks.
Here's an example script:
class Foo implements AutoCloseable {
Foo {
// set up state as needed
println("Opened a Foo!")
}
@Override
void close() throws Exception {
// tear down state as needed
println("Closed a Foo!")
}
}
def main() {
new Foo().withCloseable {
// baz()
println("Hello!")
}
}
main()
Cheers,
Leo
On Sat, Nov 21, 2020 at 11:29 AM Milles, Eric (TR Technology)
<[email protected]<mailto:[email protected]>> wrote:
Groovy Devs,
I have been pondering how to automate the writing of try/finally blocks used to
unconditionally restore object state. Does anyone know of a Groovier way to do
something like this before I pursue a macro method, an AST transformation, or
something more involved? It currently requires a lot of typing to do this.
Scenario 1: stack-ify a scalar field/property -- often used when traversing a
list or tree and "state" is the current element
class Foo {
private state
def bar() {
def temp = state // may be any number of fields saved to temp vars
state = newState
try {
baz()
} finally {
state = temp
}
}
def baz() {
// make use of state; does not require previous values
}
}
Scenario 2: mutation rollback -- similar but "state" is not written to
beforehand
class Foo {
private state
def bar() {
def temp = state // may be any number of fields saved to temp vars
try {
baz()
} finally {
state = temp
}
}
def baz() {
// modifies state
}
}
Note: "state" is not always convertible into a java.util.Stack. Sometimes this
is 3rd-party code that is being extended.
I was thinking of something like this so as not to overload the try keyword:
class Foo {
def bar() {
push (field1 = value, field2) { // AST would be re-written to try/finally
like Scenario 1/2
baz()
}
}
...
}
This e-mail is for the sole use of the intended recipient and contains
information that may be privileged and/or confidential. If you are not an
intended recipient, please notify the sender by return e-mail and delete this
e-mail and any attachments. Certain required legal entity disclosures can be
accessed on our website:
https://www.thomsonreuters.com/en/resources/disclosures.html