groovy-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Winnebeck, Jason" <>
Subject RE: How to determine the equality of two closures?
Date Thu, 13 Apr 2017 15:24:46 GMT
I wrote my reply before I saw your use case of Gradle build scripts. My technique probably
won’t work there because I assume the build script is re-compiled between each run so would
give a different class object, but I don’t know how the up-to-date check works…

Here is what I did. In this example each time runScript runs and calls watch, despite the
“cond” closure being different instances each time, they are all of the same class so
that’s how I know it’s the same call site. However, if I made another function “runScript2”
even if it had identical code, the closures would not compare “equal” for my use case
(which in my watch case, is exactly what I’d want anyway).

def person = [name: 'Jason', skills: ['Groovy']]

def watches = [:] = { cond, action, elseAction ->
def value = person.with(cond).clone()
def lastValue = watches[cond.class]
if (value != lastValue) action(lastValue, value) else elseAction()
watches[cond.class] = value

void runScript(def p) {{skills},
         {o, n -> println "Skills are now $n"},
         {println "Skills have not changed"})

person.skills << 'Java'

Skills are now [Groovy]
Skills have not changed
Skills are now [Groovy, Java]

From: bo zhang []
Sent: Thursday, April 13, 2017 11:05 AM
Subject: Re: How to determine the equality of two closures?

Sorry Jason, but I don't quite understand, would you please explain it more detailedly? Thanks
a lot.

2017-04-13 22:28 GMT+08:00 Winnebeck, Jason <<>>:
Jochen, I had a use case that was very close to this that may or may not inspire bo zhang
for an alternative solution to closure equality. I had to rely on the Groovy implementation
detail that each Closure instance created from an expression at a line of code had the same
class (I did put this assumption in a unit test in my project so I'd know if that broke).
That let me create a DSL like AngularJS watches:

def person = [name: 'Jason', skills: ['groovy']] {skills} ) {oldVal, newVal ->
  println "person.$name's skills changed from $oldVal to $newVal"

To implement the watch method, I have a map of Class to watcher's state. So when the
expression is run again, the state is preserved from the last run, using the closure's class
as the key to recover the state. In this example, two watches with the same closure definition
would have two states. But if I put the two watch into a function, the closures would share
the same line of code and compare as "equal"


-----Original Message-----
From: Jochen Theodorou [<>]
Sent: Thursday, April 13, 2017 10:08 AM
Subject: Re: How to determine the equality of two closures?

On 13.04.2017 15:56, bo zhang wrote:
> Hello everybody,
> I just have encountered a problem thus need your help. I want to treat
> the following closures as "equivalent":
> Clousure c1={
> "This is a closure"
> }
> Clousure c2={
> "This is a closure"
> }
> assert closureEqual(c1,c2)

may I ask how you want to use that? I was thinking about this in the past, but I failed to
create a reasonable scenario in which I would need this.

> Apparently, even though all fields and methods (the internal bytecode)
> are equal, c1 and c2 are still different classes (xxx_closure$1 and
> xxx_closure$2). AFAIK, everything but name in these two classes are equal.
> Is there any possibilities to achieve my goal? Thank you very much.

right now, not no.

bye Jochen
This email message and any attachments are for the sole use of the intended recipient(s).
Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the
intended recipient, please contact the sender by reply email and destroy all copies of the
original message and any attachments.

View raw message