Details
-
New Feature
-
Status: Closed
-
Major
-
Resolution: Duplicate
-
None
-
None
-
None
Description
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
Attachments
Issue Links
- duplicates
-
GROOVY-4998 Real currying support
- Open