Map myProcesses = [coolId : { retriever.somehow() }] myProcesses.coolId() // <-- the first time this invokes a method call myProcesses.coolId() // <-- should return value stored from the last call
The use of the closures worked nicely, I just had to figure out how to handle caching. At first I looked into the memoize method on my closures, but there seemed to be some disconnect between how I was trying to use them and what Groovy wanted. When I used coolId() it complained that the method doCall was not available. So, I'm not exactly sure what was happening there.
Map myProcesses = [coolId : { retriever.somehow() }.memoize()]
Then I realized I should be able to do something simpler anyway. Really I wanted a LazyMap, I
didn't need caching on each individual closure. I had used the LazyMap class provided in the apache commons library to do the following.
return org.apache.commons.collections4.Map.LazyMap.lazyMap( new HashMap<String, MyObject>(), new org.apache.commons.collections4.Transformer<String, MyObject>() { @Override public MyObject transform(String input) { return retriever.goGetIt(input); } });
I also remembered coming across some LazyMap references in Groovy, so I did some looking, but the only class I found was in the groovy.json.internal package. Probably not a class I should be using. Was it possible that Groovy didn't have an implementation of a LazyMap? That seemed unlikely to me, almost everything in the commons libraries seem to be built into Groovy. So I started looking at the Groovy docs and ran across the withDefault method that Groovy added to Maps. I realized that an empty map whose default method would invoke my closures and store the results was exactly what I wanted.
Map myInnerProcesses = [coolId : { retriever.somehow() }] Map myProcesses = [:].withDefault { myInnerProcesses[it] } myProcesses.coolId() // <-- the first time this invokes a method call myProcesses.coolId() // <-- should return value stored from the last call
So, by using withDefault I was able to add caching in a single line of code.
Post a Comment