tags:

views:

177

answers:

2

Code inside closures can refer to it variable.

8.times { println it }

or

def mywith(Closure closure) {
   closure()
}

mywith { println it }

With this behavior in mind you can't expect following code to print 0011

2.times {
   println it 

   mywith {
      println it
   }
}

And instead I have to write

2.times { i ->
   println i 

   mywith {
      println i
   }
}

My question is: why closures without parameters override it variable even if they don't need it.

+3  A: 

I think it has something to do with the formal Closure definition of Groovy:

Closures may have 1...N arguments, which may be statically typed or untyped. The first parameter is available via an implicit untyped argument named it if no explicit arguments are named. If the caller does not specify any arguments, the first parameter (and, by extension, it) will be null.

That means that a Groovy Closure will always have at least one argument, called it (if not specified otherwise) and it will be null if not given as a parameter.

The second example uses the scope of the enclosing closure instead.

Daff
Thanks for formal definition
Mykola Golubyev
+2  A: 

If you define a closure like this

def closure = {println "i am a closure"}

It appears to have no parameters, but actually it has one implicit parameter named it. This is confirmed by:

def closure = {println "i am a closure with arg $it"}
closure("foo")

which prints

"i am a closure with arg foo"

If you really want to define a closure that takes 0 parameters, use this:

def closure = {-> println "i am a closure"}

Your example could therefore be rewritten as:

2.times {
   println it 

   mywith {->
      println it
   }
}
Don
Thanks. Explicit zero-parameters closure won't look nice in mini-dsls.
Mykola Golubyev