2013-01-22 12 views
13

Używam wielu bibliotek w Clojure, które produkują funkcje wyższego rzędu, które są zgodne z interfejsem "clojure.lang.IFn".Czy będę mógł używać funkcji Clojure jako Lambdas w Java 8?

Ma wiele przeciążeń przez przeciążenia, tj. interfejs wygląda mniej więcej tak:

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) ; 
} 

Czy będę mógł korzystać z tego typu obiektów bezpośrednio w Java 8 jako wywoływalne funkcji lambda?

+5

IIRC, Java 8 nie pozwala na "wywoływanie" funkcji lambda w jakikolwiek nowy sposób; zapewnia tylko nowe sposoby tworzenia _ funkcji lambda, które muszą być interfejsami jednofunkcyjnymi. –

Odpowiedz

7

Co masz na myśli, używaj obiektów tego typu jako kaloszy lambdas?

W bardzo prostych przypadkach Java 8 lambdas mogą być traktowane jako cukru składniowej + jakiś rodzaj wnioskowania do anonimowego klas dla pewnego typu interfejsów, mianowicie interfejsów funkcjonalnych[1]:

Interfejs ActionListener, użyty powyżej, ma tylko jedną metodę. Wiele wspólnych interfejsów wywołań zwrotnych ma tę właściwość, na przykład Runnable i Comparator. Damy wszystkim interfejsom, które mają tylko jedną metodę, nazwę: interfejsy funkcjonalne.

Uwaga: lambdy naprawdę nie są tylko cukrem; wewnętrznie są one implementowane inaczej niż anonimowe klasy, a także istnieją pewne różnice semantyczne; zobacz this excellent answer na ProgrammersExchange po więcej informacji na ten temat. Nie jest to jednak tak ważne w kontekście tego pytania i odpowiedzi.

Wszędzie tam, gdzie oczekiwana jest wartość jakiegoś interfejsu funkcjonalnego (argument metody, zmienna lokalna, deklaracja pola itp.) Możliwe będzie użycie krótkiej składni do stworzenia obiektu przypominającego klasę anonimową implementującą tę metodę, czyli lambda wyrażenie:

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(); 
    } 
}; 

Więc pytanie może być interpretowane tylko w następujący sposób: jest to możliwe, aby utworzyć obiekty typu IFn wykorzystaniem Java 8 składni lambda?

Odpowiedź brzmi: nie. Składnia Lambda jest możliwa tylko z funkcjonalnymi interfejsami. clojure.lang.IFn nie jest funkcjonalny interfejs, ponieważ zawiera dużo więcej niż jednej metody, więc nie będzie to możliwe, aby zrobić coś jak

IFn f = (String s) -> s.toLowerCase(); 
+5

Pomysł, że Java lambdy 8 to cukier syntaktyczny na anonimowych klasach wewnętrznych to mem, który po prostu nie zniknie. Zobacz odpowiedzi na to pytanie: http://programmers.stackexchange.com/questions/177879/type-inference-in-java-8, dla wyjaśnienia, dlaczego jest błędny. Będzie to z pewnością częste pytanie; Udzielę odpowiedzi na FAQ Lambda (http://www.lambdafaq.org) –

+0

@MauriceNaftalin, dziękuję, powinienem był czytać specyfikację lambda bardziej dokładnie. Dodaję informację o tym. –

+1

Moja interpretacja pytania jest przeciwieństwem tego, co tu masz.Myślę, że chce przekazać funkcje clojure, które są obiektami implementującymi interfejs IFn, do funkcji java, które oczekują obiektu implementującego swój interfejs funkcji pojedynczej. Odpowiedź, którą podejrzewam, to nie. – bfabry

2

No, wydaje się nie można korzystać z funkcji Clojure jakby są one również ważne java lambdas. Clojure's IFn nie jest zgodne z zdefiniowanymi interfejsami funkcjonalnymi Javy "lambda".

Powiązane problemy