0

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.

6
  • You mean like in C? I'd suggest write a function and call it. So from the options given the middle one seems the "most" Groovy (calling anon-function). if would mislead the reader (unless you add a constant for the true here to communicate the intent). And the any is just a hack -- if you end up in a place, that does not have a any method, this falls apart. I'd really like to see the use-case. Commented Jun 19 at 7:00
  • It might help if you explain why you want to do this? Commented Jun 19 at 22:04
  • @cfrick I want to limit the lifetime of variables for readability. For example, you have two policy files for the default and the user one. You want to parse both In the same method. Their file paths are derived by the some logic, but you don't want to abstract the logic as two functions because they will be executed only once only at one place. If you use the same scope, you need names 'defaultPolicyDir', 'defaultPolicyPath', 'userPolicyDir', 'userPolicyPath', etc. But by using separate scopes you only need names 'dir' and 'path'. Commented Jun 20 at 1:10
  • 1
    I'd still go with a function, but you could assign it just locally and call it: def load = { path, file -> ... }; load('a','n'); load('c','d') Commented Jun 20 at 16:16
  • 1
    why not just { def a = 1 }? Commented Jun 20 at 19:25

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

You can use a semicolon like the following in a recent version of Groovy. Although it's uglier than the one on the accepted answer, I think it's more readable.

;{
    def a = 1
}

In an old version of Groovy such as 2.x, you can use labeled statements like the following.

L:{
    def a = 1
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.