Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will I be able to use Clojure functions as Lambdas in Java 8?

I use a number of libraries in Clojure that produce higher order functions that conform to the "clojure.lang.IFn" interface.

It has multiple arity overloads, I.e. the interface looks something like:

public interface IFn extends Callable, Runnable{
  public Object invoke() ;
  public Object invoke(Object arg1) ;
  public Object invoke(Object arg1, Object arg2) ;
  public Object invoke(Object arg1, Object arg2, Object arg3) ;
  .... etc.
  public Object applyTo(ISeq arglist) ;
}

Will I be able to use objects of this type directly in Java 8 as callable lambda functions?

like image 445
mikera Avatar asked Jan 22 '13 06:01

mikera


2 Answers

What do you mean, use objects of this type as callable lambdas?

In very simple cases, Java 8 lambdas can be thought as syntactic sugar + some type inference for anonymous classes for certain type of interfaces, namely functional interfaces [1]:

The interface ActionListener, used above, has just one method. Many common callback interfaces have this property, such as Runnable and Comparator. We'll give all interfaces that have just one method a name: functional interfaces.

Remark: lambdas are really not just a sugar; internally they are implemented differently than anonymous classes, and there are also some semantic differences; see this excellent answer on ProgrammersExchange for more on this matter. However, this is not really important in context of this question and answer.

Anywhere where a value of some functional interface is expected (method argument, local variable, field declaration etc.) it will be possible to use short syntax for creating an entity resemling anonymous class implementing this method, that is, a lambda expression:

Runnable r = () -> {
    System.out.println("Hi");
};
// Equivalent to
Runnable r = new Runnable() {
    public void run() {
        System.out.println("Hi");
    }
};

public interface Function<F, T> {
    T call(F arg);
}

Function<String, char[]> c = s -> ("<" + s + ">").toCharArray();
// Equivalent to
Function<String, char[]> c = new Function<>() {
    public char[] call(String s) {
        return ("<" + s + ">").toCharArray();
    }
};

So your question can only be interpreted in the following way: is it possible to create objects of type IFn using Java 8 lambda syntax?

The answer is no. Lambda syntax is possible only with functional interfaces. clojure.lang.IFn is not a functional interface because it contains much more than single method, so it won't be possible to do something like

IFn f = (String s) -> s.toLowerCase();
like image 81
Vladimir Matveev Avatar answered Oct 02 '22 13:10

Vladimir Matveev


No, it seems you can not use clojure functions as if they are also valid java lambdas. Clojure's IFn does not conform to java's "lambda" functional interfaces as defined.

like image 25
matanster Avatar answered Oct 02 '22 13:10

matanster