Why isn't the value of an instance variable set in a Groovy closure visible outside of it?

Question

Why methodA()

print set within run

instead set within closure

?

Sample code

class GroovyClosureVariableScopingTest extends Script {

    String s

    Object run() {
        s = "set within run"
        println "value of s in run(): $s"

        [1].each {
            s = "set within closure"
            println "value of s in each()-closure: $s"
            methodA()
        }
    }

    void methodA() {
        println "value of s in methodA(): $s"
    }
}

      

Actual output

value of s in run(): set within run
value of s in each()-closure: set within closure
value of s in methodA(): set within run            // <- Surprised to see the original value

      

Expected Result

value of s in run(): set in run
value of s in each()-closure: set within closure
value of s in methodA(): set within closure        // <- Whould have expected this value

      

Development of

I didn't quite understand how the variable scope works in the above example. I would expect to s

be a property (public instance variable) of the class and I thought I was assigning a value from each

-closure to it to be stored. But it doesn't seem to be the case.

Why s

doesn't it store the value that was assigned from the closure?

Solution / workaround

Passing s

as an argument to methodA()

works. See the lines commented with // Change

.

class GroovyClosureVariableScopingTest extends Script {

    String s

    Object run() {
        s = "set within run"
        println "value of s in run(): $s"

        [1].each {
            s = "set within closure"
            println "value of s in each()-closure: $s"
            methodA(s)              // Change
        }
    }

    void methodA(s) {               // Change
        println "value of s in methodA(): $s"
    }
}

      

Link

Closure - formal definition

At the same time, variables are still generally available for the enclosing scope, so the closure can read / modify any such values, and code from the outer scope can read / modify the same variables.

Versions

  • Groovy 1.8.6
  • Groovy -Eclipse plugin 2.8.0
  • Eclipse 3.8.1 Platform
+3


source to share


1 answer


After user cfrick confirmed that it works on his machine, I ran it from the console and it actually works.

On the console

C:\temp>java -jar C:\...\lib\groovy-all-1.8.6.jar C:\temp\GroovyClosureVariableScopingTest.groovy
value of s in run(): set within run
value of s in each()-closure: set within closure
value of s in methodA(): set within closure // <- Here

      

With a clean install of Eclipse



But I still don't get the original script to run with a clean install

Summary

I still don't know why this doesn't work - even with a clean install of Eclipse. However, it works from the console, it works on cfrick machine and there is a workaround.

0


source







All Articles