A week or so ago I’ve contributed in the StackOverflow Documentation an entry about Currying which until now it’s mostly intact and only cosmetic changes have been made to the original. This is how it goes:
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.
This can be useful when:
- Different arguments of a function are calculated at different times. (see Example 1)
- Different arguments of a function are calculated by different tiers of the application. (see Example 2)
This generic utility applies currying on a 2-argument function:
class FunctionUtils {
public static <A,B,C> Function<A,Function<B,C>> curry(BiFunction<A, B, C> f) {
return a -> b -> f.apply(a,b);
}
}
The above returned curried lambda expression can also be viewed/written written as:
a -> ( b -> f.apply(a,b) );
Example 1
Let’s assume that the total yearly income is a function composed by the income and a bonus:
BiFunction<Integer,Integer,Integer> totalYearlyIncome = (income,bonus) -> income + bonus;
Let’s assume that the yearly income portion is known in advance:
Function<Integer,Integer> partialTotalYearlyIncome = FunctionUtils.curry(totalYearlyIncome).apply(10000);
And at some point down the line the bonus is known:
System.out.println(partialTotalYearlyIncome.apply(100));
Example 2
Let’s assume that the car manufacturing involves the application of car wheels and car body:
BiFunction<String,String,String> carManufacturing = (wheels,body) -> wheels.concat(body);
These parts are applied by different factories:
class CarWheelsFactory {
public Function<String,String> applyCarWheels(BiFunction<String,String,String> carManufacturing) {
return FunctionUtils.curry(carManufacturing).apply("applied wheels..");
}
}
class CarBodyFactory {
public String applyCarBody(Function<String,String> partialCarWithWheels) {
return partialCarWithWheels.apply("applied car body..");
}
}
Notice that the CarWheelsFactory
above curries the car manufacturing function and only applies the wheels. The car manufacturing process then will take the below form:
CarWheelsFactory carWheelsFactory = new CarWheelsFactory();
CarBodyFactory carBodyFactory = new CarBodyFactory();
BiFunction<String,String,String> carManufacturing = (wheels,body) -> wheels.concat(body);
Function<String,String> partialCarWheelsApplied = carWheelsFactory.applyCarWheels(carManufacturing);
String carCompleted = carBodyFactory.applyCarBody(partialCarWheelsApplied);