Groovy 1.8 a b c风格

时间:2011-07-11 07:07:04

标签: groovy dsl

我需要一个Groovy 1.8 DSL功能的帮助。

考虑this测试用例:

/**
 * 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
}

如果我将[milk: { drank = true }()]更改为[foo: { drank = true }()],则测试用例仍会通过。这可能是新实现中的错误还是我在Groovy语法中遗漏了什么?

编辑 - 已解决:@han和@Gareth Davis都发布了正确的线索。以下是了解此测试的更多细节:

    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 

[A]返回@han指出的地图。在[B]行中,drank已经true,因为创建后立即执行关闭(正如@Gareth Davis指出的那样),类似于JavaScript module pattern。我不认为这种“测试”是展示此功能的最佳方式 - drank的副作用是错误的。

2 个答案:

答案 0 :(得分:2)

问题在于:

def drink = { String s -> [milk: { drank = true }()] }

更改为:

def drink = { String s -> [milk: { drank = true }] }

实际上在创建时调用闭包而不是运行DSL的尾随parens。

def d = drink more milk

// d is actually a closure not a boolean you would need to invoke it in order to get the required side effect of setting drank.
d.call()

答案 1 :(得分:1)

groovy:000> drank =false
===> false
groovy:000> d = {x -> [y: {drank=true}()]}
===> groovysh_evaluate$_run_closure1@170b819
groovy:000> drank
===> false
groovy:000> d 2  
===> {y=true}
groovy:000> drank
===> true
第一次调用时的

设置为drank然后变成一个地图{y:true}

非常令人费解的行为

从中我们可以看到 有许多方法可以从新的1.8语法合成DSL - 密钥解除引用映射 - 关闭和通话 - 类和方法

要小便