Closures For OO Developers – 2 – FP in an OO Language

Reading Time 5 to 10 minutes

In a previous blog post Closures For OO Developers – 1, I described how I initially thought about closures when I came to Functional Programming. I related an inner closure having access to the environment of the outer closure that created it as being conceptually similar to an inner object having access to the properties of the outer object that created it.

I thought I would back up a bit and show that a closure can really just be thought of as a one method object. There is a quote floating around something like “A Closure is a poor man’s object and visa versa”. I’m not sure of the exact origin of that quote but really the point is that closures and objects are almost the same thing. Closures, in a sense, when thought of as one method objects, bridge the gap between OO programming and functional programming.

It is possible to apply functional programming principles in an object oriented language using closures as one method objects even when the language in question isn’t a fully featured functional programming language. I’m going to take an example of a very common transformation in functional programming – map. This is a function over a data structure which also takes a mapping function as a parameter and applies this mapping function to each element in the data structure to create new data structure elements and, ultimately, a new data structure.

Closures to make OO more Functional

Lets have a look at how this may have been achieved with closures in Java pre Java 8. I will then show the same thing in Java 8 using Java 8 lambdas which are closures.

 
 
    public static <T, U> List<U> map(List<T> list, Mapping<T, U> mapping) { 
 
        List<U> result = new ArrayList<U>(); 
        for (T elem : list) { 
            result.add(mapping.apply(elem)); 
        } 
        return result; 
    } 
 
 
    private interface Mapping<T, U> { 
        U apply(T element); 
    } 
 
    public static void main (String[] args) { 
        List<String> inputList = 
                Arrays.asList("functional", "programming", "with", "closures"); 
 
        Mapping<String, Integer> stringToStringLength = 
          new Mapping<String, Integer>() { 
            public Integer apply(String element) { 
                return element.length(); 
            } 
        }; 
        List<Integer> mappedList = map(inputList, stringToStringLength); 
        System.out.println("Initial List: " + inputList); 
        System.out.println("Mapped List: " + mappedList); 
    }

In the example above, there is a map function which takes a list but it also takes another object as a parameter which will decide how each element in the list will be transformed into a new element for the resulting list. In functional programming, functions are treated as first class values and can be passed as arguments into other functions in the same as any other type of value.

In order to do this in an OO language such as Java pre Java 8, this function argument, mapping, needs to be first wrapped in a one method object. In this case the one method object will be an implementation of the one method interface, Mapping. This interface has one method, apply. The method is essentially the first class function that could be passed around in a functional programming language. An instance of this one method interface can be called a closure. In functional programming, this one method object is represented simply as a function and can also be called a closure.

The main method uses this map function to transform a list of strings into a new list representing the length of each string in the original list. An instance of the Mapping interface is created with an anonymous class. This is the one method object or closure or “function” which is passed as an argument to the map function in order to tell the map function how to transform the list of strings.

Lambdas/Closures in Java 8 – Coating on one Method Objects

Now lets refine the above example a bit to show how, essentially, Java 8 hides this under the covers (but I’m sure it provides optimisations along the way) with its lambda syntax.

 
 
    public static <T, U> List<U> map(List<T> list, Function<T, U> mapping) { 
 
        List<U> result = new ArrayList<U>(); 
        for (T elem : list) { 
            result.add(mapping.apply(elem)); 
        } 
        return result; 
    } 
 
    public static void main (String[] args) { 
        List<String> inputList = 
                Arrays.asList("functional", "programming", "with", "closures"); 
 
        List<Integer> mappedList = map(inputList, s -> s.length()); 
 
        System.out.println("Initial List: " + inputList); 
        System.out.println("Mapped List: " + mappedList); 
    }

In the above example, the Mapping interface is no longer required because Java 8 has a library of one method interfaces, called Functional Interfaces, out of the box. The map function, apart from using the Java 8 Function interface, has remained the same in its implementation. In the main method, instead of having to create and instantiate an anonymous class, we can use a Java 8 lambda which is essentially a function implementation.
s -> s.length()
This is defining a function implementation which takes a String (or anything which has a .length() method and returns an Integer) and returns the length of that String. It can really be thought of as a syntax replacement for the anonymous one method class that we had to declare in the previous example.

Refined more with Java 8 Streams

Using Java 8 streams we can take this further by simply using the map method already available on Java 8 streams. It is typical for any functional programming language to provide this map method out of the box.

 
 
    public static void main (String[] args) { 
        List<String> inputList = 
                Arrays.asList("functional", "programming", "with", "closures"); 
 
        List<Integer> mappedList = inputList.stream().map(s -> s.length()).collect(toList()); 
 
        System.out.println("Initial List: " + inputList); 
        System.out.println("Mapped List: " + mappedList); 
    }

The above example is refined to use Java 8 streams. The whole transformation can now be done in the main method using the map function from the Java 8 API. The lambda which is passed to this function remains unchanged from the one passed to the earlier implementation of map.

Haskell Beauty!!

To finish, here is the same mapping transformation implemented in the fully fledged, pure functional programming language that is Haskell.

map length ["functional", "programming", "with", "closures"]

In the Haskell above, we are simply declaring that we want to map the length function over the list of strings.

Conclusion

Thanks for reading this. I hope this post brought some value to developers looking to move into the functional programming world and also to developers already doing functional programming along with anyone with any other interest in functional programming. Feel free to comment.

Leave a Reply

Your email address will not be published. Required fields are marked *