Function Curry in Java8




One of the important features of a functional program is Function Currying.As we know java8 introduce lambda which brings some functional nature in java programming. We are blessed that by an intelligent use of Lambda we can create Function currying by own. Although Java8 does not have Currying facilities we can create it by ourselves. In this section, I will discuss the detail step How to create Currying in Java 8.



What is a Function Currying?
To understand the function currying let first understand what is a Partial function.

A partial function is the application of a part of a function.

To be very simple, Suppose I have a java method called add which takes two arguments as input then capability of applying one argument is called the Partial function.

Maybe you are astonished in this moment why the hell we need to do that?

Let me tell you, This is a very rich concept and it helps you to write a rich API and reduce the Repeating of yourself (DRY). It actually eliminates the conceptual duplication.

Now I am trying to describe it with a example so you can understand the above paragraph well.

Suppose, I want to write a generic compute function which takes two inputs and takes a BiFunction (Java 8 functional Interface) so I can pass behavior on the fly which will be applied to the two inputs argument.

Example

public  Integer compute(Integer a, Integer b,BiFunction<Integer,Integer,Integer> function){      
       return function.apply(a,b);
    }


By this compute method I can apply add, multiply, division whatever on these passing parameters a and b.

So I will call the Compute function in following way
BiFunction<Integer,Integer,Integer> addFunction =  (a,b)-> a+b;
Integer summation = fc.compute(50, 20, addFunction);
System.out.println("Summation is " + summation);

The output will be 70, as BiFunction called addFunction which do the adding.

Now suppose we have to build another logic, Say I pass a number then a base will automatically apply to it. The base value is  10.

So if the base is 10 and I pass 20 then the output will be 10 + 20 =30(base + actual parameter).

How would you write this function?

Very easy isn’t it, we should write it in the following manner

public Integer baseCompute(Integer value,Function<Integer,Integer> function){
       return function.apply(value);
    }


It takes a value and a Function which takes one Integer as input and return another Integer So that this function takes the passing value apply base to it and return the resultant value.

We call this baseCompute method by the following call,

Function<Integer,Integer> baseFunction =  (value)-> 10 + value;//declare base
      Integer baseResult = fc.baseCompute(20,baseFunction);
      System.out.println("Base computation " + baseResult);


The output will be 30.
So far so good, But if you are a Clean coder you are not happy with it because you observe

BiFunction<Integer,Integer,Integer> addFunction =  (a,b)-> a+b;
Function<Integer,Integer> baseFunction =  (value)-> 10 + value;

The addFunction and baseFunction body are same, so you duplicate your code breaking the DRY principle. So you must search for an option where you can reuse the same addFunction instead of writing a new baseFunction, But the problem is the Structure of addFunction is different from the base function. addFunction takes two parameters and base takes one, But conceptually both are doing same work,

addFunction add two parameters, baseFunction takes one parameter and add base value internally.

Think How you can solve the problem while I taking a short break for breakfast.

We can solve this problem, by fixing a parameter in the bi-function. As we know the base value is 10 so if we apply that value and take another value from caller then we can reuse the BiFunction.

So we could rewrite the baseCompute method like following

 public Integer applyPartialInternalCompute(Integer value,BiFunction<Integer,Integer,Integer> function){
       return function.apply(10,value);
    }


And calls the above method like following

BiFunction<Integer,Integer,Integer> addFunction =  (a,b)-> a+b;
Integer baseInternal = fc.applyPartialInternalCompute(20, addFunction);
 System.out.println("Base Internal " + baseInternal);



Congrats you have written your first partial function, Where you fixed you first parameter and takes a parameter from Caller.

It is the essence of Partial function apply a partial part of the function and returns a new function which can take remaining arguments. So it is consists of two thing



  1. Applying a part.
  2. Return a new function after applying one argument.

Mathametically

f ( x , y ) = x+y
After applying the  first parameter of function
f(2,y)=N(y)=2+y; where N(Y) is a new function returned after currying.


But what we did in our applyPartialInternalCompute method is not returning a new function or the intermediate function after partial applying the first value- Which is base value,  so it is not properly curryed this is very basic version, Let see how can we improve the function so we can get the new intermediate function after applying the first argument base.

public Function<Integer,Integer> applyPartialExternalCompute(Integer base,BiFunction<Integer,Integer,Integer> function){
       return value->function.apply(base,value);
    }


This is a more sophisticated version, It takes a Bi-function and a base value, Then apply the base value to the BiFunction and return a new Function which takes One parameter from the caller and returns another Integer.

So this function works as an adapter, It takes Bi-function applying a parameter or fixing a parameter and returns new Intermediate function to work upon,


BiFunction<Integer,Integer,Integer> = Fixed Base value + Function<Integer,Integer>

Please note that the returning function is looks  like of our baseFunction   Function<Integer,Integer> baseFunction =  (value)-> 10 + value;//declare base

This is called Function Currying, so we can use the BiFunction at fullest, So a BiFunction can take two parameters also it serves any functionality which takes one argument by fixing the first one.

How to call the applyPartialExternalCompute method,

Integer basepartial= fc.applyPartialExternalCompute(10, addFunction).apply(20);
System.out.println("Base External " + basepartial);


Our above solution is very good, and we properly use function Currying to remove conceptual duplication but wait there is still some glitch in the method we have written.

It takes Bi-function and a value and returns a Function, So every time we invoke this method it applies the parameter to BiFunction and return a new Function, But why should we perform two steps every time if we got the readymade intermediate function then we just apply our values,
Suppose there is a function which takes three arguments then we have to write two adapter functions one takes tri-function and return a Bi-function and another takes Bi-function and return a function,

So if parameter values are n we have to write n-1 adaptor methods. Which is again a duplication, So if the Curry function itself generates all intermediate structures then it will be a full proof solution lets implement this,

public   Function<Integer,Function<Integer,Integer>> applyCurryingCompute(BiFunction<Integer,Integer,Integer> function){
       return value->(base->function.apply(base,value));
    }


Yes, we are waiting for this implementation, and it is the Crux of this article, By above Curry function we should have every intermediate function and we can do any functionality by fixing others,

It takes a Bi-Function which returns an Intermediate function which takes an argument and returns a function which again takes another argument and lastly returns an Integer.

Hard to understand,

Then see the following transformation to understand what actually going on

(x,y)->z = x->(y->z)   BiFunction changes it structure after currying and create a new structure
(Integer,Integer)=Integer - > Integer =Integer->( Integer->Integer)

f(y)=x->f(x,y)=z where x->f(x,y) means x applied on Bifunction creates a function of y which is equivalent to Z

So (x->y)->z = x->(y->z).


How to call above applyCurryingCompute method

Integer baseCurry= fc.applyCurryingCompute(addFunction).apply(10).apply(20);
System.out.println("Base Curry " + baseCurry);


The full version of the program

package com.example.function.curry;

import java.util.function.BiFunction;
import java.util.function.Function;

public class FunctionCurrying {
   
    public  Integer compute(Integer a, Integer b,BiFunction<Integer,Integer,Integer> function){      
       return function.apply(a,b);
    }
    public Integer baseCompute(Integer value,Function<Integer,Integer> function){
       return function.apply(value);
    }
   
    public Integer applyPartialInternalCompute(Integer value,BiFunction<Integer,Integer,Integer> function){
       return function.apply(10,value);
    }
    public Function<Integer,Integer> applyPartialExternalCompute(Integer base,BiFunction<Integer,Integer,Integer> function){
       return value->function.apply(base,value);
    }
   
    public   Function<Integer,Function<Integer,Integer>> applyCurryingCompute(BiFunction<Integer,Integer,Integer> function){
       return value->(base->function.apply(base,value));
    }
   
   
    public static void main(String[] args) {
       FunctionCurrying fc = new FunctionCurrying();
       BiFunction<Integer,Integer,Integer> addFunction =  (a,b)-> a+b;
       Function<Integer,Integer> baseFunction =  (value)-> 10 + value;
       Integer summation = fc.compute(50, 20, addFunction);
       System.out.println("Summation is " + summation);
       Integer baseResult = fc.baseCompute(20,baseFunction);
       System.out.println("Base computation " + baseResult);
       Integer baseInternal = fc.applyPartialInternalCompute(20, addFunction);
       System.out.println("Base Internal " + baseInternal);
       Integer basepartial= fc.applyPartialExternalCompute(10, addFunction).apply(20);
       System.out.println("Base External " + basepartial);
       Integer baseCurry= fc.applyCurryingCompute(addFunction).apply(10).apply(20);
       System.out.println("Base Curry " + baseCurry); 
     
     
   }  
   

}




Conclusion: Function Currying is a rich technique, In the functional program we use it often to get rid of conceptual duplication. You can use it in Java 8 now so Please use the concept wisely.

stream api in java 8

JAVA8 Stream API
The most powerful feature in Java8 is introducing Java.Util.Stream package.

By Steam API, We can do filter,map,reduce like operations on a collection . It is very useful as many times we need to filter a collection based on some criteria.
Like, find the Employee who has a salary greater than 20000.

In order to do these prior to Java8, we need to iterate over the collection then check each employee’s salary. If it is greater than 20000 we need to put it in an another list. Then print out that list. This is very time-consuming and unnecessary work for a developer.

But in Java8 we can do it on the fly. No need to do all those prior java8 stuff.
Now we have Stream interface you can invoke stream() function or parallelStream function on Collection to get Stream Interface.

In-Stream interface you can do multiple useful operations like filter the stream based on
Criteria to do that just need to pass a Java.util.function.Predicate which contains the filter criteria.

As java8 also support Lambda Expression you can pass the predicate as an argument of a method.

Please read my article on java lambda Expression to know about this

Enough theory lets do some coding

Suppose I want to filter Employees  of a company based on their salary,department,sex,manager

By Java8 we do it very easily by using filter Operation

Step 1:
Create an Employee class

package com.example.java;

public class Employee {
           
            String name;
            String sex;
            boolean manager;
            Integer salary;
            String dept;
           
            public String getName() {
                        return name;
            }
            public void setName(String name) {
                        this.name = name;
            }
            public String getSex() {
                        return sex;
            }
            public void setSex(String sex) {
                        this.sex = sex;
            }
            public boolean isManager() {
                        return manager;
            }
            public void setManager(boolean manager) {
                        this.manager = manager;
            }
            public Integer getSalary() {
                        return salary;
            }
            public void setSalary(Integer salary) {
                        this.salary = salary;
            }
            public String getDept() {
                        return dept;
            }
            public void setDept(String dept) {
                        this.dept = dept;
            }
            @Override
            public String toString() {
                        return "Employee [name=" + name + ", sex=" + sex + ", manager="
                                                + manager + ", salary=" + salary + ", dept=" + dept + "]";
            }
           
           
           
           
           
           

}


Step 2:

Create another class which will perform filtering operation on Employee list

package com.example.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;

import com.example.java.Employee;

public class EmployeeUtiltyStream {
           

           
            List<Employee> list = new ArrayList<Employee>();
           
            public EmployeeUtiltyStream()
            {
                        init();
                       
            }
           
            private void init()
            {
                        Employee emp = new Employee();
                        emp.setName("Shamik Mitra");
                        emp.setManager(false);
                        emp.setSex("Male");
                        emp.setSalary(20000);
                        emp.setDept("Java");
                       
                        Employee emp1 = new Employee();
                        emp1.setName("Aman Verma");
                        emp1.setManager(true);
                        emp1.setSex("Male");
                        emp1.setSalary(50000);
                        emp1.setDept("IOT");
                       
                        Employee emp2 = new Employee();
                        emp2.setName("Priti Dey");
                        emp2.setManager(true);
                        emp2.setSex("FeMale");
                        emp2.setSalary(40000);
                        emp2.setDept("Mainframe");
                       
                        Employee emp3 = new Employee();
                        emp3.setName("Ajay Ghosh");
                        emp3.setManager(false);
                        emp3.setSex("Male");
                        emp3.setSalary(30000);
                        emp3.setDept("Java");
                       
                        list.add(emp);
                        list.add(emp1);
                        list.add(emp2);
                        list.add(emp3);
            }
           
            public void filterList(Predicate<Employee> predicate) {
                         
                        Stream<Employee> employeeStream = list.parallelStream();
                       
                        Stream<Employee> filteredEmployeeStream = employeeStream.filter(predicate);
                       
                        filteredEmployeeStream.forEach(employee->System.out.println(employee));
                       
            }
           
           
           
            public static void main(String[] args) {
                       
                        EmployeeUtiltyStream employeeUtiltyStream = new EmployeeUtiltyStream();
                       
                        employeeUtiltyStream.filterList(employee->employee.getSalary()<=40000);
                        System.out.println("****************************************");
                        employeeUtiltyStream.filterList( employee->employee.getSex().equalsIgnoreCase("FeMale"));
                        System.out.println("****************************************");
                        employeeUtiltyStream.filterList( employee->employee.isManager());
                        System.out.println("****************************************");
                        employeeUtiltyStream.filterList( employee->employee.getDept().equalsIgnoreCase("Java"));
                       
                       
                       
            }

}



Please look this class very carefully
I create a init method where I add Employees in a List.

Then I create a method call filterList which takes a java.util.function.Predicate class as argument

public void filterList(Predicate<Employee> predicate) {
                         
                        Stream<Employee> employeeStream = list.parallelStream();
                       
                        Stream<Employee> filteredEmployeeStream = employeeStream.filter(predicate);
                       
                        filteredEmployeeStream.forEach(employee->System.out.println(employee));
                       
            }


To get Stream class, I invoke parallelStram method on employee list.
Then call filter method and pass the predicate.

Now look at main method

employeeUtiltyStream.filterList(employee->employee.getSalary()<=40000);

here I invoke filterList method and pass Predicate using a lambda expression
in Predicate I say filter employee based on a salary less than 40,000

guess what output is

Employee [name=Shamik Mitra, sex=Male, manager=false, salary=20000, dept=Java]
Employee [name=Ajay Ghosh, sex=Male, manager=false, salary=30000, dept=Java]
Employee [name=Priti Dey, sex=FeMale, manager=true, salary=40000, dept=Mainframe]
****************************************
Employee [name=Priti Dey, sex=FeMale, manager=true, salary=40000, dept=Mainframe]
****************************************
Employee [name=Priti Dey, sex=FeMale, manager=true, salary=40000, dept=Mainframe]
Employee [name=Aman Verma, sex=Male, manager=true, salary=50000, dept=IOT]
****************************************
Employee [name=Ajay Ghosh, sex=Male, manager=false, salary=30000, dept=Java]

Employee [name=Shamik Mitra, sex=Male, manager=false, salary=20000, dept=Java]