Skip to content

CurriedFunctionsLogicalLimits

Robert Peszek edited this page Sep 14, 2013 · 1 revision

Curried Functions Logical Design Limits

Logical Requirement:

To be able to convert a closure to a curried function, closure has to logically represent a 'curried function type'. Basically, Fpiglet needs to know how many parameters does it have and the answer needs to be just one number.

You can think of that as being able to 'mentally define' in pseudo-Haskell syntax type for closure like so:

def c = {a, -> {b,c,d-> a + b + c + d}}
//c3:: (NotGroovyClosure r) => a -> b-> c -> d -> r
//(I do not care what a,b,c,d is but r is not a Groovy closure)

or simply said, we need to know that c needs to have 4 curried parameters.

There is a few problems related to that and to how Groovy closures work.

Design Limitations:

1: Handling of Optional Parameters:

Groovy allows you to have optional parameters like so:

def fc = f {a,b=0 -> {c,d=0-> a + b + c + d}}
//this has 4 curried parameters a,b=0,c,d=0

So we have optional (curried) parameter in the middle! What does fc(1,2) mean? Parameter a is applied 1, but were 2 goes? Could go to either b or c and if it goes to c could the result be a number (d=0) or a closure with one optional parameter? So some decision needs to be made. Fpiglet treats all optional parameters (in the middle) as non-optional. So the second argument will go to parameter b. Current implementation works like so in fpiglet:

assert fc(1,2,3,4) == 10
assert fc(1)(2)(3)(4) == 10

I am not sure if this behavior will stay. but the best thing to do is not to use optional parameters when defining curried functions!

2: Arbitrary number of parameters:

In Groovy, you can define closures which accept any number of parameters like so:

def c = {Object[] args -> ...}
def c2 = {a, Object[] args -> ...}

I simply cannot guess number of parameters to proceed. Note: closures like {Object[] args -> ...} are used in fpiglet implementation of curried closures (see my next post).

Current Fpiglet behavior is like so:

Closure fc2 = f {a , Object[] args -> [a, args.length]} 
assert fc2(1) instanceof Closure
assert fc2(1,2) == [1,1]
//fc1(1,2,3) //fails

also do not expect Fpiglet do convert closures inside arbitrary param closure into curried functions:

Closure fc2 = f {Object[] args -> {a,b -> ...}} 

You would need to do this instead:

Closure fc2 = {Object[] args -> f {a,b -> ...}} 

3: Logically invalid curried functions:

Example:

def c = {a -> 
 if(a) 
   return {b-> println "$a $b"} 
 else 
   return {b,c-> println "$a $b $c"}
}

Hey c so how many curried parameters can I pass to you? Two, three? Closure like this does not represent a curried function and should be not used with Fpiglet.

Clone this wiki locally