I need help with one of the Groovy 1.8 DSL features.
Consider this test case:
/**
* For odd number of elements, treat the last element as a call to a getter
*
* case a b c
* equivalent a(b).getC()
*/
void testTrailingElementAsGetter() {
def drank = false
def more = 'more'
def drink = { String s -> [milk: { drank = true }()] }
def d = drink more milk
assert drank
}
If I change [milk: { drank = true }()] to [foo: { drank = true }()], the test case still passes. Could this be a bug in the new implementation or am I missing something in the Groovy syntax?
EDIT – SOLVED: Both @han and @Gareth Davis posted the right clues. Here are some more details to understand this test:
groovy:000> more = 'more'
===> more
groovy:000> drank = false
===> false
groovy:000> drink = { String s -> [milk: { drank = true }()] }
===> groovysh_evaluate$_run_closure1@20c87621
[A] groovy:000> drink more
===> {milk=true}
[B] groovy:000> drank
===> true
groovy:000> drink more milk
===> true
groovy:000> drink more water
===> null
Line [A] returns a map as @han pointed out. In line [B], drank is already true, due to the closure executing immediately after creation (as @Gareth Davis pointed out), similar to the JavaScript module pattern. I don’t think this “test” is the best way to showcase this feature – the side-effect on drank is mis-leading.
x on first invoke sets drank to true then becomes just a map {y : true}
quite a puzzling behaviour really
from this we can see
there are many ways to synthesize a DSL from the new 1.8 syntax
– key-dereferencing maps
– closure and call
– class and method
be bary