Saturday, 3 June 2017

Prelude to Functional Paradigm.

When we talk about Functional Programming, then Functions holds the key to computing instead of Variables.

Functions are the first class citizen of Functional Programming Paradigm. Whether it is Lambdas in Java8 or Closures in Groovy both aid to Functional programming and in the best possible way.

Does the features that Java8 embeds, shifts its paradigm to Functional Programming Horizon? Basically being a beginner with these tools that has been introduced in Java8, I would try to answer it in the following way: It's true that java 8 provides the platform for Functional Programming now but the imperative style too is dominant. I think may be It is the Best of Both Worlds that we all will be trying to look into and incorporate as per our needs. With all the new features in Java 8 like Lambdas, Monads, Functor, Upgraded collection API with Streams etc., Java now extend its support for Functional Programming.

But the question arises why Functional Programming is gaining popularity more and more.

The main idea behind functional programming is that Functions are being considered as the First Class Citizen here. It is the Function(or Method) reference that we pass as arguments (which we will see in a while) and upon when needed we apply arguments to those function references and evaluate them.

Data Invariance lies at the heart of any Functional Programming language which we can describe as that each function produces results without affecting/modifying the environment and by this way we can go for parallel programming without any side-effects.

Basically what I have experienced that following Functional Style makes the application inherently Thread safe as every Function upon invocation returns an Immutable Object (following Data Invariance) which again is passed to some other function. Monads, Functor and other constructs mainly contribute to these.

Basically a Pure Functions acts on its arguments passed and produce results without any side effects (i.e. without the interference of any State Variables or other types) and thus helps in building Thread Safe apps.

Groovy is a Functional Programming Language which is Dynamic in Nature but can be Static typed too.

So, Lambdas in Java8 and Closures in Groovy are those two facets which seems structurally similar at their first sight, but the underlying implentation and their applicability provides a clear distinction.

So, how Lambdas differ from Closures? We have a Functional Interface:


@FunctionalInterface
public interface Func1 {
    R transform(T t);
}

and we invoke it as:
 
    static Func1 stringIntegerFunction = s -> s.length();
    Assert.assertEquals(stringIntegerFunction.transform("Mickey"), new Integer(5));
 
 
The Functional Interface implentation is done with a Lambda expression and then invoked from within main method. A Functional Interface basically follows SAM (Single Abstract Method) Rule.
Similarly if we need to declare a Closure that Takes a String as input and has Integer as return type, then we can define that as:
   Closure func1 = {String str -> str.length()}
 
and even as:
  Closure func2 = { str -> str.length()}
 
The difference being one being Typed and other not. For Groovy Closure we dont need to define any Functional Interface.

We can then invoke them as:
  Assert.assertEquals  func1('Mickey'), 5
  Assert.assertEquals func2('Mickey'), 5
 
If take a closer look at the Lambdas, then Lambdas are basically anonymous implentations of mostly Java 8 Functional Interfaces, But on the other hand Closure in Groovy is class, that Groovy Runtime Dunamically generates an instance of it (Closure class) when it encounters Closure expressions.

The feature that really impressed me is the Delegation Starategy of the closure, which adds a lot to the type nature of the groovy along with the type inference feature of the closure, which too is awesome. We do not need to decalare any type while declaring the closure, it deduces the type based on the parameter passed at runtime (Duck Typing), however we can can Strongly type a Closure too. These feature often turns out to be source Of Confusion too.

The Delegation strategy may seem a bit confusing at first, but it is really interesting as we learn more about it.

Since Groovy documentation has detailed explantion of Closure and all other features (as said above and Many more) so we will restrict our discussion in that direction.

Another feature is that Groovy closure can access any variable from it enclosing context, while Java lambdas can access only variables which are final or effectively final. This post is not intended in any way to mark out the differences between Groovy or Java.

But it is all about how I am experiencing Functional Programming paradigm when I am just starting to learn the best of both these worlds. And also a bit explaining how Lambdas and Closures and used interchageably. Almost everything that Lambdas does can be achieved with Closures and Perhaps More!!!

We will try to point out some cool Closure features through some unit tests.
class ClosureSpec extends Specification {
 
 def "test closure"(){
 
  when:
   def retVal = function([1,"Mic"],{str1,str2 -> str1.size()+" Paul "+ Arrays.asList(str2)})
  
  then:
   retVal('Mic') == "2 Paul [Mic]"
 
 }
 
 def function(str,cl){
        return { name->
            cl(str,name)
        }
    }
 
}
 

Here the Function named function takes two parameters and returns a Closure.

We have passed List as the first parameter and a closure as the second parameter. Now this closure takes two parameters in its input and does some processing. As a return type we have returned a Closure which again takes another parameter as its input.

Now when we have invoked the function:
  def retVal = function([1,"Mic"],{str1,str2 -> str1.size()+" Paul "+ Arrays.asList(str2)})
a closure is returned i.e. retVal and then we have called the Closure with 'Mic' to get the desired output.
retVal('Mic') == "2 Paul [Mic]"
Here no Type has been mentioned with any parameters, the types are being deduced based on the data passed.Now if we pass something to str1 where the method size() cannot be allowed say an Integer then we will be getting an error for sure. Now in the second demo:
we have defined a List as:
def names = ['Mickey','Mic',100]
and a Closure as:
 def cls = {str ->  println "My New Name is: $str"}
 
This Closure takes a String as an argument and prints out a message bearing that argument.
Now if we need to pass this closure to the each() of the List, then we would do something like this.
  names.each (cls)
or
names.each {cls(it)}

Now if we want a method reference to be passed as argument to each() method of List class we would declare the method as:

 def transform(str){
        println "My Name is: $str"
    }

and pass it as:

 names.each {this.&transform(it)}
Or

names.each(this.&transform)

Now if we want to do the same in Java8 we would do something like this:
List list = Arrays.asList("Mickey", "Mic", "Donald");
and invoke them as:
 list.stream().forEach(s -> System.out.println(s));
 
Or:
 
 public void printEach(String str){
        System.out.println(str);
    }
 
  list.stream().forEach(this::printEach);
 
 
forEach() method expects an argument of Consumer Type which is a Functional Interface.
So Closures and Lambdas almost goes side by side. Now to find the interoperability between these two, lets declare a Method in Java which takes a Fnctional Interface and try to invoke it passing a Closure from Groovy.
 
 Class A{
 public static Integer getMeLength(Func1 func1, String str){
        return func1.transform(str);
    }
 }
 
Then we can invoke it as:
  Assert.assertEquals  LambdaTest.getMeLength({str -> str.length()}, "Donald Duck"), 11
  Assert.assertEquals  LambdaTest.getMeLength(func1, "Donald Duck"), 11
  Assert.assertEquals  LambdaTest.getMeLength(func2, "Donald Duck"), 11
 
Please Note: func1 and func2 are the closures that we had defined earlier.

Groovy Closures do not bind themselves specifically to any Functional Interfaces or any interface that confirms to SAM, we can represent both SAM or implement any interface (be it SAM or not) with a Groovy Closure, thats the flixibility that Closure comes with.

However, Lambdas are more centric towards Functional Interface or SAM.

This is in short and very basic note on Java8 Lambdas and Groovy Closures.
View Subhankar Paul's profile on LinkedIn

No comments:

Post a Comment