groovyscope

How to define a new scope?


Currently, I am considering these three methods to define a new scope.

if (1) {
    def a = 1
}
({
    def a = 1
})()
any {
    def a = 1
}

Is there anyone better? It seems the official style guide does not cover this topic.

I don't care any performance overhead if the readability is good.


Solution

  • You can have blocks like in other languages for isolating scope of variables, but there is a catch.

    A block { ... } in Groovy can also be used to define a closure; it implies a one-arity, with the first argument named it. The parser will assume a closure unless it's after a term, that regularity has a block (e.g. if, while, ...). And Groovy allows putting last-argument-closures to be placed on their own.

    a(x, { it }) ⇔ a(x) { it }
    

    If you have code before a new block, Groovy will use this block as a closure argument for the code before in last place instead. You have to tell the parser, what is going on, and put a ; at the end of the line before, to prevent this. E.g.

    {
        def a = "foo"
        println(a) ; // XXX
        {
            def b = "baz"
            println b
        }
    }
    {
        def a = "bar"
        println a ; // XXX
        {
            def b = "qux"
            println b
        }
    }
    

    That said, I'd still rather use a (anon)-function to do the work here. Above code is not idiomatic Groovy and the error, if you forget the ;, is pointing to the problem (e.g. that println above has no signature for (object, closure)). But there is always the odd chance, that your line before actually takes an optional closure, and then things can become really confusing.