项目作者: mtumilowicz

项目描述 :
Overview of groovy closure currying.
高级语言: Groovy
项目地址: git://github.com/mtumilowicz/groovy-closure-currying.git
创建时间: 2018-11-17T17:35:57Z
项目社区:https://github.com/mtumilowicz/groovy-closure-currying

开源协议:

下载


Build Status

groovy-closure-currying

Overview of groovy closure currying.

Reference: https://www.jstips.co/en/javascript/curry-vs-partial-application/
Reference: https://en.wikipedia.org/wiki/Currying
Reference: https://en.wikipedia.org/wiki/Partial_application
Reference: https://en.wikipedia.org/wiki/Arity

preface

currying

In mathematics and computer science, currying is the technique of
translating the evaluation of a function that takes multiple
arguments into evaluating a sequence of functions, each with a
single argument. For example, a function that takes two arguments,
one from X and one from Y, and produces outputs in Z, by currying
is translated into a function that takes a single argument from X
and produces as outputs functions from Y to Z. Currying is related
to, but not the same as, partial application.

example

  • add: X x X -> X
    1. function add(x, y) {
    2. return x + y;
    3. }
  • curried add: X -> (X -> X)
    1. function curriedAdd(x) {
    2. return function (y) {
    3. return x + y;
    4. }
    5. }
  • calling:
    1. add(3, 5);
    2. curriedAdd(3)(5);

partial application

In computer science, partial application (or partial function application)
refers to the process of fixing a number of arguments to a function,
producing another function of smaller arity (arity of a function or
operation is the number of arguments or operands that the function takes).

example

  • add: X x X -> X
    1. function add(x, y) {
    2. return x + y;
    3. }
  • partial add: X -> X
    1. function partialAdd_5(y) {
    2. return add(5, y);
    3. }
  • calling:
    1. add(5, 3);
    2. partialAdd_5(3);

currying vs partial application

  • currying

    Currying takes a function

    f: X x Y -> R

    and turns it into a function

    f': X -> (Y -> R)

    Thus, if the uncurried f is invoked as

    f(3,5)

    then the curried f’ is invoked as

    f'(3)(5)

  • partial application

    Partial application takes a function

    f: X x Y -> R

    and a fixed value for the first argument to produce a new function

    f': Y -> R

    f’ does the same as f, but only has to fill in the second
    parameter which is why its arity is one less than the arity of f.

groovy currying

In Groovy, currying refers to the concept of partial application.
It does not correspond to the real concept of currying in functional
programming because of the different scoping rules that Groovy
applies on closures.

Please refer my other github project:
https://github.com/mtumilowicz/groovy-closure-owner-delegate-this

Currying in Groovy will let you set the
value of one parameter of a closure, and it will return a new
closure accepting one less argument.

It is quite useful with .& operator:
https://github.com/mtumilowicz/groovy-transform-method-to-closure

We have 3 approaches to currying in groovy:

  • Left currying - setting the left-most parameter of a closure
  • Right currying - setting the right-most parameter of a closure
  • Index based currying - In case a closure accepts more than
    2 parameters, it is possible to set an arbitrary parameter using ncurry

project description

We provide tests in Currying class:

  • left currying

    1. given:
    2. def divide = { x, y -> x / y }
    3. when:
    4. def curriedDivide = divide.curry(10)
    5. then:
    6. curriedDivide(2) == 5
  • right currying

    1. given:
    2. def divide = { x, y -> x / y }
    3. when:
    4. def curriedDivide = divide.rcurry(10)
    5. then:
    6. curriedDivide(20) == 2
  • index based currying

    1. given:
    2. def concat = { a, b, c, d, e -> String.join(",", a, b, c, d, e) }
    3. when:
    4. def currierConcat = concat.ncurry(2, "c", "d", "e")
    5. then:
    6. currierConcat("a", "b") == "a,b,c,d,e"
  • currying with method reference

    1. given:
    2. def curriedAdd = Currying.&add.curry(5)
    3. expect:
    4. curriedAdd(2) == 7

    where:

    1. static int add(x, y) {
    2. return x + y
    3. }