2013-01-22 102 views
13

我在Clojure中使用了許多符合「clojure.lang.IFn」接口的高階函數庫。我能否在Java 8中使用Clojure函數作爲Lambdas?

它有多個重載重載,即,界面看起來是這樣的:

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

請問我能不能直接在Java中8個調用lambda函數使用這種類型的對象?

+5

IIRC,Java 8不允許您以任何新方式「調用」lambda函數;它只提供了_create_ lambda函數的新方法,它必須是單功能接口。 –

回答

7

你是什麼意思,使用這種類型的對象作爲可調用的lambdas?

非常簡單箱子,爪哇8層的lambda 可以被認爲是語法糖+匿名類中的某些類型推斷對於某些類型的接口,即功能接口[1]

接口上面使用的ActionListener只有一個方法。很多 常見的回調接口都有這個屬性,比如Runnable和 比較器。我們將給所有隻有一個方法的接口提供一個名稱:功能接口 。

備註:lambdas真的不只是一個糖;在內部它們的實現方式與匿名類不同,並且也存在一些語義差異;有關此事的更多信息,請參見ProgrammersExchange上的this excellent answer。但是,在這個問題和答案中,這並不重要。

任何需要某個函數接口的值的地方(方法參數,局部變量,字段聲明等),可以使用短語法來創建實現此方法的匿名類的實體,也就是lambda表情:

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

所以你的問題只能通過以下方式解釋:是否有可能創建使用Java 8 lambda語法IFn類型的對象?

答案是否定的。 Lambda語法僅適用於功能接口。 clojure.lang.IFn是不是功能界面,因爲它包含了比單一方法多得多,所以它不可能做這樣的事情

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

Java 8 lambda是匿名內部類上的語法糖的想法是一個不會消失的模因。查看這個問題的答案:http://programmers.stackexchange.com/questions/177879/type-in​​ference-in-java-8,解釋爲什麼它是錯誤的。這顯然是一個常見的問題;我會在Lambda FAQ(http://www.lambdafaq.org) –

+0

@MauriceNaftalin上回答一個問題,謝謝,我應該更詳細地閱讀lambda規範。我正在添加一個關於它的通知。 –

+1

我對這個問題的解釋與你在這裏得到的結果相反。我認爲他希望將實現接口IFn的對象的clojure函數傳遞給期望實現其單個函數接口的對象的java函數。我懷疑的答案是否定的。 – bfabry

2

沒有,看來你不能使用Clojure的功能,就好像他們也是有效的Java lambda表達式。 Clojure的IFn不符合java定義的「lambda」功能接口。