Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-990

Closure access to outer block variables - inconsistant behavior

    XMLWordPrintableJSON

Details

    Description

      Closure using a variable outside its enclosing block has inconsistant behavior. A series of tests demonstrate the issue. In most cases if the closure is defined in a function/method works fine, but behaves incorrectly in script code (in the invisible main ). The test to demonstrate the problem is as follows:

      println "Tests for groovy closure's use of 'outer scope variable'"
      println "Sone strange behavior"
      println "Some are a little unexpected but correct - but fails the 'least unexpected' test"

      def test0() {
      def list = []
      for(i in ["red","green","blue"]) {

      list <<

      { println i }
      }
      i = "Strange"
      println println "Test0 logical – although somewhat unexpected - prints Strange ... \n-------"

      // execute each of the 3 closures in 'list'
      for( x in list) { x() }
      println()
      }

      def test1() {
      def list = []
      for(i in ["red","green","blue"]) {
      def v = i
      list << { println v }
      }
      println "Test1 Fix test0 to give the desired behavior\n-------"

      // execute each of the 3 closures in 'list'
      for( x in list) { x() }
      println()
      }

      // An alternative method of achieving the expected behavior
      def test2() {
      def list = []
      for(i in ["red","green","blue"]) {
      list << { println it }.curry
      }
      println "Test2 OK (another way to fix the problem using curry)\n-------"

      // execute each of the 3 closures in 'list'
      for( x in list) { x() }
      println()
      }

      //
      def test3() {
      def lis = []
      ["red","green","blue"].each { v ->
      lis << { println v }
      }


      println "Test3 OK\n-------"
      for( x in lis ) { x() }
      println()
      }

      //
      def test3A() {
      def lis = []
      ["red","green","blue"].each { v ->
      def X = v
      lis << { println X }
      }


      println "Test3A OK – very similar to test3\n-------"
      for( x in lis ) { x() }
      println()
      }


      // Execute the tests
      test0()
      test1()
      test2()
      test3()
      test3A()

      // This is code outside of a function
      // this does not work right

      // Test4
      def list = []
      for(i in ["red","green","blue"]) {
      def v = i
      list << { println v }
      }
      println "Test4, Should have given red blue green \n-------"
      for( x in list) { x() }
      println()

      // Test 5
      def lis = []
      ["red","green","blue"].each { i ->

      lis << { println i }


      }
      println "Test5, does give red blue green \n-------"
      for( x in lis)

      { x() }
      println()

      // Test 5A
      def lisx = []
      ["red","green","blue"].each { v ->
      def X = v
      lisx << { println X }
      }
      println "Test5A, is almost identical to test3A, but behaves differently \n-------"
      for( x in lisx) { x() }


      println()

      // Test 6
      def li = []
      println "Test6, fails again \n-------"
      ["red","green","blue"].each { s ->
      def v1 = s
      li <<

      { println v1 }


      }

      for( x in li)

      { x() }


      println()

      Attachments

        1. test.grv
          2 kB
          nurul choudhury

        Issue Links

          Activity

            People

              blackdrag Jochen Theodorou
              nurulc nurul choudhury
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: