Details

    • Type: New Feature New Feature
    • Status: Open Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: 3.0
    • Component/s: groovy-jdk
    • Labels:
      None
    • Number of attachments :
      0

      Description

      Hi.

      Groovy's Closure have a name of method 'curry'.
      But this is not work for a real currying, it work as a partial function application.
      So, I wrote method of 'Real currying'.

      Referenced http://en.wikipedia.org/wiki/Currying

      Closure add = {a, b, c -> a + b + c } // Closure of adding 3 arguments.
      
      assert add(1, 2, 3) == realCurry(add)(1)(2)(3)
      assert 6 == add(1, 2, 3)
      def curriedAdd = realCurry(add)
      def curriedAdd_1 = curriedAdd(1)
      def curriedAdd_1_2 = curriedAdd_1(2)
      def addResult = curriedAdd_1_2(3)
      assert 6 == addResult
      
      def realCurry(Closure clos) {
        if (clos.maximumNumberOfParameters >= 1) {
          return { x ->
            def cc = clos.curry(x)
            if (cc.maximumNumberOfParameters) realCurry(cc)
            else cc()
          }
        } else {
          return clos
        }
      }
      

      (It's also published on gist https://gist.github.com/1193548)

      I hope this will be adopted to Groovy core.

      Thank you.

        Issue Links

          Activity

          Hide
          blackdrag blackdrag added a comment -

          the point you are referring to is realCurry(add)(1)(2)(3), instead of our add.curry(1).curry(2).curry(3). Furthermore add.curry(1) results in an add, in which the first argument will be 1 and only second and third can be applied any more, while realCurry(add) returns a function that takes only one argument and returns then a new function, in which add will have 1 set as first argument, but again accepts only one argument. Applying the final argument gives the result then.

          Yoshida, do you have some examples in which you can show the advantage of real currying over partial function application?

          Show
          blackdrag blackdrag added a comment - the point you are referring to is realCurry(add)(1)(2)(3), instead of our add.curry(1).curry(2).curry(3). Furthermore add.curry(1) results in an add, in which the first argument will be 1 and only second and third can be applied any more, while realCurry(add) returns a function that takes only one argument and returns then a new function, in which add will have 1 set as first argument, but again accepts only one argument. Applying the final argument gives the result then. Yoshida, do you have some examples in which you can show the advantage of real currying over partial function application?
          Hide
          Kentaro Yoshida added a comment -

          Hi, Jochen Theodorou.

          Beginning of what is I thought that the name of curry evokes not partial function application but real currying.
          So, I wrote realCurry code.

          But, well on second thought, For Groovy, 'realCurry' is perhaps not necessary because it can partial function application by a curry method on Closure, even if function is not fully curried like Haskell.

          If possible, please adding that curry method works as partial function application on API documentation?

          Thank you.

          Show
          Kentaro Yoshida added a comment - Hi, Jochen Theodorou. Beginning of what is I thought that the name of curry evokes not partial function application but real currying. So, I wrote realCurry code. But, well on second thought, For Groovy, 'realCurry' is perhaps not necessary because it can partial function application by a curry method on Closure, even if function is not fully curried like Haskell. If possible, please adding that curry method works as partial function application on API documentation? Thank you.
          Hide
          Russel Winder added a comment -

          Jochen,

          I think the point here is that this is another case of the Groovy label being a mish-mash of concepts as understood in the wider world. The Groovy curry function is not performing a curry, hence Kentaro Yoshida's point. Can I suggest that this is marked "not a bug" for Groovy 1, but in Groovy 2 this is sorted out (along with what a closure is) so that Groovy aligns with the commonly accepted meanings of these jargon words?

          { a , b , c -> a + b + c }.curry ( ) == { a -> { b -> { c -> a + b + c } } }
          
          Show
          Russel Winder added a comment - Jochen, I think the point here is that this is another case of the Groovy label being a mish-mash of concepts as understood in the wider world. The Groovy curry function is not performing a curry, hence Kentaro Yoshida's point. Can I suggest that this is marked "not a bug" for Groovy 1, but in Groovy 2 this is sorted out (along with what a closure is) so that Groovy aligns with the commonly accepted meanings of these jargon words? { a , b , c -> a + b + c }.curry ( ) == { a -> { b -> { c -> a + b + c } } }
          Hide
          blackdrag blackdrag added a comment -

          sure we can do, thought I cannot guarantee it will be taken over like this. Also what name should our curry then have?

          Show
          blackdrag blackdrag added a comment - sure we can do, thought I cannot guarantee it will be taken over like this. Also what name should our curry then have?
          Hide
          Russel Winder added a comment -

          The function currently called curry is really partial application so partial. However might it be possible to have a sophisticated call mechanism so that:

          { a , b , c -> a + b + c } ( 2 ) == { a , b -> 2 + a + b }
          

          clearly I am taking some liberties with the equality operator here

          Show
          Russel Winder added a comment - The function currently called curry is really partial application so partial. However might it be possible to have a sophisticated call mechanism so that: { a , b , c -> a + b + c } ( 2 ) == { a , b -> 2 + a + b } clearly I am taking some liberties with the equality operator here
          Hide
          blackdrag blackdrag added a comment -

          I would prefer not to do that directly on Closure, because I want the error message sometimes. But it is possible

          Show
          blackdrag blackdrag added a comment - I would prefer not to do that directly on Closure, because I want the error message sometimes. But it is possible
          Hide
          Masato Nagai added a comment -

          I think a thing we do to fix this issue is renaming 'curry' to 'partial'.

          Show
          Masato Nagai added a comment - I think a thing we do to fix this issue is renaming 'curry' to 'partial'.
          Hide
          CÚdric Champeau added a comment -

          Well, I think it's too late to rename curry. Just like our closures not being closures stricly speaking.

          Show
          CÚdric Champeau added a comment - Well, I think it's too late to rename curry . Just like our closures not being closures stricly speaking.
          Hide
          Pascal Schumacher added a comment -

          This is a copy of Robert Peszek comment from the closed duplicate of this issue:

          I would like to propose a new feature which would make Groovy Closures stand out from Java 8 lambdas. I would like Groovy to add support for Curried Functions.

          The following code example should explain what I mean. This code shows how partial application currently works in Groovy:

             Closure c1 = {a, b, c, d-> "${a},${b},${c},${d}"}
             Closure c2 = {a -> {b -> {c -> {d -> "${a},${b},${c},${d}"}}}}
             Closure c3 = {a, b -> {c, d -> "${a},${b},${c},${d}"}}
             
             shouldFail(MissingMethodException){ c1(1) }
             assert c1(1,2,3,4) == "1,2,3,4"
             
             shouldFail(MissingMethodException){ c2(1,2,3,4) }
             assert c2(1)(2)(3)(4) == "1,2,3,4"
             
             shouldFail(MissingMethodException){ c3(1,2,3,4) }
             shouldFail(MissingMethodException){ c3(1) }
             //... etc, etc
             
             //showcase Groovy verbose curry
             assert c1.curry(1).curry(2).curry(3).curry(4) instanceof Closure
             assert c1.curry(1).curry(2).curry(3).curry(4).call() == "1,2,3,4"
          

          Continuing the above example, imagine that Groovy has 'f' which transforms closure into a 'curried function':

             //test what Fpiglet does
             showcaseCurriedFunctions c1
             showcaseCurriedFunctions c2
             showcaseCurriedFunctions c3
          
             void showcaseCurriedFunctions(Closure c){
               Closure fc = f c //same as CallUtil.toFunction(c)
               
               assert fc(1,2,3,4) == "1,2,3,4"
               assert fc(1)(2)(3) instanceof Closure
               assert fc(1)(2)(3)(4) == "1,2,3,4"
          
               assert fc(1)(2,3,4) == "1,2,3,4"
               assert fc(1,2,3)(4) == "1,2,3,4"
               //... etc, etc
             }  
          

          Such transformation is actually not very hard to implemented and is part of Fpiglet open source: http://code.google.com/p/fpiglet/

          I believe that this functionality can be implemented better within the language.

          Why Curried Functions?
          In a nutshell, curried functions make partial application terse and intuitive. They are a great starting point towards more functional code.

          Consider these 2 code examples which do essentially the same thing:

           //Standard Groovy
           def sumSquares = list.collect{it * it}.inject{acc, el -> acc + el}
          

          and

           //curried function version may look like this (note << is both closure composition and can be used to pass argument to Closure):
           def sumSquares = reduceL(PLUS) << map(POWER(_,2)) << list
          

          (This should serve as example to show how curried functions are useful, I am not suggesting Groovy re-implements its collections API.)

          There is only one 'first class citizen' in the standard Groovy example: it is the list object, collect method is 'owned' by the list.

          By contrast, in the second example: `map`, `POWER`, `POWER(,2)`, `map(POWER(,2))`, `reduceL`, `PLUS`, `reduceL(PLUS)` are all first class citizens, they all live on their own.
          Data (`list`) and data manipulation (`reduceL(PLUS) << map(POWER(_,2))`) become decoupled.

          This input-output chain syntax is possible because of curried functions. `map` needs 2 parameters (Closure and a List) but it is given 1, `POWER` needs 2 parameters (2 numbers) but it is given 1, `reduceL` needs 2 parameters (Closure and a List) but it is given 1.

          Closures in Groovy can be viewed as first class citizens and functions.
          However, the current idiomatic usage of closures treats them
          only as either

          • short lived anonymous lambdas
          • means to achieve expressive DSL syntax (e.g. Builders)

          Function composition is supported by the language but is is never (or almost never) used by Groovy practitioners.
          Adding support for Curried Functions could change all of that and make Closures stand out more in Groovy language.

          Thank you for considering this request.
          Fpiglet implementation of this functionality can be found here:
          http://code.google.com/p/fpiglet/source/browse/#svn%2Ftrunk%2Ffpiglet%2Fsrc%2Fgroovy%2Ffpig%2Futil%2Fcurring

          Show
          Pascal Schumacher added a comment - This is a copy of Robert Peszek comment from the closed duplicate of this issue: I would like to propose a new feature which would make Groovy Closures stand out from Java 8 lambdas. I would like Groovy to add support for Curried Functions . The following code example should explain what I mean. This code shows how partial application currently works in Groovy: Closure c1 = {a, b, c, d-> "${a},${b},${c},${d}" } Closure c2 = {a -> {b -> {c -> {d -> "${a},${b},${c},${d}" }}}} Closure c3 = {a, b -> {c, d -> "${a},${b},${c},${d}" }} shouldFail(MissingMethodException){ c1(1) } assert c1(1,2,3,4) == "1,2,3,4" shouldFail(MissingMethodException){ c2(1,2,3,4) } assert c2(1)(2)(3)(4) == "1,2,3,4" shouldFail(MissingMethodException){ c3(1,2,3,4) } shouldFail(MissingMethodException){ c3(1) } //... etc, etc //showcase Groovy verbose curry assert c1.curry(1).curry(2).curry(3).curry(4) instanceof Closure assert c1.curry(1).curry(2).curry(3).curry(4).call() == "1,2,3,4" Continuing the above example, imagine that Groovy has 'f' which transforms closure into a 'curried function': //test what Fpiglet does showcaseCurriedFunctions c1 showcaseCurriedFunctions c2 showcaseCurriedFunctions c3 void showcaseCurriedFunctions(Closure c){ Closure fc = f c //same as CallUtil.toFunction(c) assert fc(1,2,3,4) == "1,2,3,4" assert fc(1)(2)(3) instanceof Closure assert fc(1)(2)(3)(4) == "1,2,3,4" assert fc(1)(2,3,4) == "1,2,3,4" assert fc(1,2,3)(4) == "1,2,3,4" //... etc, etc } Such transformation is actually not very hard to implemented and is part of Fpiglet open source: http://code.google.com/p/fpiglet/ I believe that this functionality can be implemented better within the language. Why Curried Functions? In a nutshell, curried functions make partial application terse and intuitive. They are a great starting point towards more functional code. Consider these 2 code examples which do essentially the same thing: //Standard Groovy def sumSquares = list.collect{it * it}.inject{acc, el -> acc + el} and //curried function version may look like this (note << is both closure composition and can be used to pass argument to Closure): def sumSquares = reduceL(PLUS) << map(POWER(_,2)) << list (This should serve as example to show how curried functions are useful, I am not suggesting Groovy re-implements its collections API.) There is only one 'first class citizen' in the standard Groovy example: it is the list object, collect method is 'owned' by the list. By contrast, in the second example: `map`, `POWER`, `POWER( ,2)`, `map(POWER( ,2))`, `reduceL`, `PLUS`, `reduceL(PLUS)` are all first class citizens, they all live on their own. Data (`list`) and data manipulation (`reduceL(PLUS) << map(POWER(_,2))`) become decoupled. This input-output chain syntax is possible because of curried functions. `map` needs 2 parameters (Closure and a List) but it is given 1, `POWER` needs 2 parameters (2 numbers) but it is given 1, `reduceL` needs 2 parameters (Closure and a List) but it is given 1. Closures in Groovy can be viewed as first class citizens and functions. However, the current idiomatic usage of closures treats them only as either short lived anonymous lambdas means to achieve expressive DSL syntax (e.g. Builders) Function composition is supported by the language but is is never (or almost never) used by Groovy practitioners. Adding support for Curried Functions could change all of that and make Closures stand out more in Groovy language. Thank you for considering this request. Fpiglet implementation of this functionality can be found here: http://code.google.com/p/fpiglet/source/browse/#svn%2Ftrunk%2Ffpiglet%2Fsrc%2Fgroovy%2Ffpig%2Futil%2Fcurring
          Hide
          Robert Peszek added a comment - - edited

          My apologies for entering almost duplicate ticket.

          I would like to emphasize maybe subtle but important difference in what I am proposing:

          The original proposal requires that arguments are passed to curried function one at a time. I am proposing that any valid number of arguments can be passed. Using code example from ticket description, all below should work:

           realCurry(add)(1, 2, 3)
           realCurry(add)(1)(2,3)
           realCurry(add)(1,2)(3)
           realCurry(add)(1)(2)(3)
          

          This would allow much easier to read code, using reduceL example I could write:

            reduceL(PLUS)  //partially applied
            reduceL(PLUS, list)  //evaluated
            reduceL(_, list) //maybe Groovy could support this simple syntax for partially applying second arg?
          

          Semantics: The original ticket defines real curried function as a function in curried form. My proposal defines curried function as equivalence class of functions which have the same curried form.

          The approach suggested by ticket description mimics curried functions in SCALA. What I am proposing mimics curried functions in Haskell. Why go half way only and settle on SCALA? After all how can you argue with Haskell on what curried function should be

          Again, thanks for considering my suggestions. I believe Haskell style curried functions lead to much more powerful idiomatic use.

          Show
          Robert Peszek added a comment - - edited My apologies for entering almost duplicate ticket. I would like to emphasize maybe subtle but important difference in what I am proposing: The original proposal requires that arguments are passed to curried function one at a time. I am proposing that any valid number of arguments can be passed. Using code example from ticket description, all below should work: realCurry(add)(1, 2, 3) realCurry(add)(1)(2,3) realCurry(add)(1,2)(3) realCurry(add)(1)(2)(3) This would allow much easier to read code, using reduceL example I could write: reduceL(PLUS) //partially applied reduceL(PLUS, list) //evaluated reduceL(_, list) //maybe Groovy could support this simple syntax for partially applying second arg? Semantics: The original ticket defines real curried function as a function in curried form . My proposal defines curried function as equivalence class of functions which have the same curried form. The approach suggested by ticket description mimics curried functions in SCALA. What I am proposing mimics curried functions in Haskell. Why go half way only and settle on SCALA? After all how can you argue with Haskell on what curried function should be Again, thanks for considering my suggestions. I believe Haskell style curried functions lead to much more powerful idiomatic use.
          Hide
          blackdrag blackdrag added a comment -

          Robert, my problem with this issue is still the same. I need an example, close to Groovy, that shows the benefit. Where and how exactly in reduceL(PLUS) << map(POWER(_,2)) << list you use the real currying?

          Show
          blackdrag blackdrag added a comment - Robert, my problem with this issue is still the same. I need an example, close to Groovy, that shows the benefit. Where and how exactly in reduceL(PLUS) << map(POWER(_,2)) << list you use the real currying?

            People

            • Assignee:
              Unassigned
              Reporter:
              Kentaro Yoshida
            • Votes:
              1 Vote for this issue
              Watchers:
              8 Start watching this issue

              Dates

              • Created:
                Updated: