groovy
  1. groovy
  2. GROOVY-5301

closures do not handle 'it' correctly

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Minor Minor
    • Resolution: Not A Bug
    • Affects Version/s: 1.8.5
    • Fix Version/s: None
    • Component/s: groovy-jdk
    • Labels:
    • Environment:
      Windows command line (to reduce dependencies)
    • Number of attachments :
      0

      Description

      Running the following script shows 'it' as being null:

      dec = { it ->
      def x = it
      return { println "$

      {x--}

      (was $it)" }
      }

      def f = dec(2)
      f(); f();

      Output is:
      2 (was null)
      1 (was null)

      If the 'it' references are changed to 'val', then it works fine - i.e. says '(was 2)'

      This also fails when no parameter is used (i.e. defaulting to 'it')

        Activity

        Hide
        Andrew Stratton added a comment -

        Please see comments if necessary.

        Show
        Andrew Stratton added a comment - Please see comments if necessary.
        Hide
        Andrew Stratton added a comment -

        Hi Paul
        Yes - I get it now - its the second closure that has 'it' nulled out.

        e.g.
        f1 = { val ->
        def x = val-1
        return

        { println "$val -> $x" }

        }
        (f1(2))()
        ===
        2 -> 1
        This works, because val exists in the scope outside of the second closure call.

        f2 = { it ->
        def x = it-1
        return

        { println "$it -> $x" }

        }
        (f2(2))()
        (f2(2))(3)
        ===
        null -> 1
        3 -> 1

        This shows what is really happening with the original example - 'it' referred to the parameterless call to second closure.

        One last example to confirm:
        f3 = { it ->
        def x = it-1
        return

        { y -> println "$it -> $x" }

        }
        (f3(2))()
        (f3(2))(3)
        ===
        2 -> 1
        2 -> 1

        Yep - the 'it' parameter is initialized to the passed parameter - or null if none is provided - but when aparameter name is used, 'it' is left alone.

        Cheers
        Andy

        Show
        Andrew Stratton added a comment - Hi Paul Yes - I get it now - its the second closure that has 'it' nulled out. e.g. f1 = { val -> def x = val-1 return { println "$val -> $x" } } (f1(2))() === 2 -> 1 This works, because val exists in the scope outside of the second closure call. f2 = { it -> def x = it-1 return { println "$it -> $x" } } (f2(2))() (f2(2))(3) === null -> 1 3 -> 1 This shows what is really happening with the original example - 'it' referred to the parameterless call to second closure. One last example to confirm: f3 = { it -> def x = it-1 return { y -> println "$it -> $x" } } (f3(2))() (f3(2))(3) === 2 -> 1 2 -> 1 Yep - the 'it' parameter is initialized to the passed parameter - or null if none is provided - but when aparameter name is used, 'it' is left alone. Cheers Andy
        Hide
        Paul King added a comment -

        Is this not what is expected? You are returning a closure - you have not supplied any args to that closure, hence "it" for the closure is null (even though the outer closure will have a different "it" value).

        Show
        Paul King added a comment - Is this not what is expected? You are returning a closure - you have not supplied any args to that closure, hence "it" for the closure is null (even though the outer closure will have a different "it" value).

          People

          • Assignee:
            Unassigned
            Reporter:
            Andrew Stratton
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: