Hi Eric,

do these references (it seems you do not need to open the can of worms that is deep copying in your problem) you need to save/restore reside in a single class, or could such a class be introduced (maybe in a generic manner) ? I am unclear how wide the different scenarios are here you want to solve in a generic manner...

Cheers,
mg


On 22/11/2020 02:03, Milles, Eric (TR Technology) wrote:

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 <leo...@gmail.com>
*Sent:* Saturday, November 21, 2020 5:34 PM
*To:* dev@groovy.apache.org
*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) <eric.mil...@thomsonreuters.com <mailto:eric.mil...@thomsonreuters.com>> 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
    <https://www.thomsonreuters.com/en/resources/disclosures.html>


Reply via email to