On 29 March 2017 at 14:56, Nelson, Erick <erick.nel...@hdsupply.com> wrote: > I'm not sure using or not using def would cause performance differences.
There definitely *seems* to be a difference. def rng = new MersenneTwister() def roll = { rng.nextInt(6) + rng.nextInt(6) + rng.nextInt(6) + 3 } Both def: 0.4 to 0.5 sec No def on rng, def on roll: 0.5 to 0.8 sec - spread seems greater, too Def on rng, not on roll: 1.2 to 1.6 sec, with a couple of 1.9s. Def on neither: 1.4 to 1.9 sec. int roll() and no def on rng looks similar to def on roll and not on rng. But def on rng isn't allowed when I'm using int roll(). All results from multiple runs on my PC, summarising the average/spread by eye. So the big difference is removing def from roll, with removing def from rng having a smaller but detectable effect. > It just affects variable scope. > > http://mrhaki.blogspot.com/2009/11/groovy-goodness-variable-scope-in.html I still find this confusing. That article says that def or type are equivalent (in terms of scope). But int roll() doesn't allow def rng, whereas def roll does. I assume that the issue here is that def roll = { ... } is making roll an attribute whose value is a closure. Whereas int roll() { ... } is making roll a method? So that implies that you can't reference a def from within a method, but you can reference it from within a closure? OK, as a rule I can accept that might be the case, but I don't understand why. Furthermore, I can't even refer to rng as "this.rng" from within roll, which is very confusing, as I thought a script was compiled as an implicit class, in which case isn't this the instance of that class, and hence this.attr should be a means of accessing any attribute of the class? Looking at the details in the manual ("Program Structure" section 3 "Scripts vs Classes") I think I start to understand: * def roll = { } is declaring a local variable in the implied run() method, whose value is a closure * roll = { } declares a variable in the "script binding" whose value is a closure * int roll { } is a method of the script class * def rng = ... is a local variable of the run method, which the docs explicitly state is not available to methods * rng = ... is a variable in the script binding which *is* visible from methods * @Field rng = ...is a field, which is what I'd need to use for this.rng to work as I'm expecting I'll have to look some more into the script binding. I don't really understand the visibility rules for values in the binding, apart from the few cases explicitly noted (e.g. "they are available from methods"). Wow, this is more complicated than it looks at first glance!!! On the other hand, fields, methods, closures and script bindings are all very different things, so I can easily imagine them having different performance characteristics. In don't know how I'd develop an intuition about which is the right one to use in any specific situation, though. Try them all and see which works better feels like the only practical option at the moment :-( Thanks, Paul