batilei
batilei

Reputation: 431

The variable scope in Groovy Closure (global variable and function parameter have same name)

I am new to Groovy and confusing about the variable scope in closure.

For example, the code below works fine. It prints two 5.

def x = 10
def y = 25

def myfunc(x) {
  return {
      println(x)
      insideFunc(x)
  }
}

def insideFunc(x) {
    println(x)
}

closureFunc = myfunc(5)

closureFunc.call()

But the code below would show error: groovy.lang.MissingPropertyException: No such property: x for class. Why? I thought the insideFunc can access the global variable 'x'?

def x = 10
def y = 25

def myfunc(x) {
  return {
      println(x)
      insideFunc()
  }
}

def insideFunc() {
    println(x)
}

closureFunc = myfunc(5)

closureFunc.call()

Upvotes: 2

Views: 3384

Answers (1)

ernest_k
ernest_k

Reputation: 45309

The problem with the second script is due to how the script is executed. x is local-scoped in the run method. That should become evident when one looks at what the script turns into when it's executed. From groovyConsole, the following is what "Inspect AST" displays (this is incomplete):

public class script1526974299557 extends groovy.lang.Script { 

    ...

    public java.lang.Object run() {
        java.lang.Object x = 10
        java.lang.Object y = 25
        closureFunc = this.myfunc(5)
        closureFunc.call()
    }

    public java.lang.Object myfunc(java.lang.Object x) {
        return { 
            this.println(x)
            this.insideFunc()
        }
    }

    public java.lang.Object insideFunc() {
        this.println(x)
    }
}

Clearly, x is out of scope for insideFunc().

Regarding the first version, however, things look different. As insideFunc() takes a parameter, it's argument is carried by the closure:

public class script1526974614817 extends groovy.lang.Script { 

    ...

    public java.lang.Object myfunc(java.lang.Object x) {
        return { 
            this.println(x)
            this.insideFunc(x)
        }
    }

    public java.lang.Object insideFunc(java.lang.Object x) {
        this.println(x)
    }
}

Upvotes: 2

Related Questions