2017-03-07 42 views
2

我有時會編寫java方法,特別是對於基本類型/數組操作,我一直在關於如何在Clojure 1.8下使用類型提示。我看到一些線索,但他們(或許?)過時了,因爲他們已經在2年多前發佈了。Clojure:類型提示塔

我會給出一個基本的例子來說明我的觀點(我知道這個例子有點無意義)。在這裏,我想總結兩個double並返回double

這裏是一個Java方法:

public static double add (double a, double b) { 

    return a + b; 
} 

然後我想有一個Clojure的包裝:

版本1

(defn d+ ^double 
    [^double a ^double b] 
    (Doubles/add a b)) 

2版

(defn d+ ^double 
    [^double a ^double b] 
    (Doubles/add ^double a ^double b)) 

版本3

(defn d+ ^double 
    [^double a ^double b] 
    (Doubles/add (double a) (double b))) 

我不知道把提示類型放在哪裏以及如何放置它們。我覺得(double x)效率較低,因爲它是一個函數(也許我錯了?)。 那麼在身體功能或外部提示提示之間有什麼區別?

也許這些提示是不必要的,因爲在Java類中只有一個方法? 我沒有看到邏輯如此普遍我使用版本1或3(更多更好?)。

請注意,對於此示例,Clojure +總是更快

+1

* *警告反射*標誌將有助於這種探索。只要將其設置爲true,編譯器就會發出信號,指出它無法選擇所需的方法過載並需要提示。 – leetwinski

+0

謝謝我已經測試過,最後還是不需要提示。你知道爲什麼這個函數比較慢,因爲它只適用於double?我的直覺是互操作隱含了一些隱藏的操作/成本,因此Java互操作只有在函數成本高昂(如大算法)或函數不存在於Clojure中時才值得。 –

+0

@leetwinski原始類型提示與反射警告無關,這些提示是針對對象的。原始提示是爲了避免拳擊的表現。更好的辦法是在clojure文件的乞討中啓用''(set!* unchecked-math *:warn-on-boxed)''。 – ClojureMostly

回答

3

版本1是正確的。它會發出以下字節碼:

public final class compile_inspect$d_PLUS_ extends AFunction implements DDD { 
    public compile_inspect$d_PLUS_() { 
    } 

    public static double invokeStatic(double a, double var2) { 
     return Primitives.add(a, var2); 
    } 

    public Object invoke(Object var1, Object var2) { 
     return new Double(invokeStatic(RT.uncheckedDoubleCast((Number)var1), RT.uncheckedDoubleCast((Number)var2))); 
    } 

    public final double invokePrim(double var1, double var3) { 
     return invokeStatic(var1, var3); 
    } 
} 

哪裏Primitives.add就像你Doubles/add功能。

如果你想表現,並避免拳擊,你應該設置:

(set! *unchecked-math* :warn-on-boxed) 

通過Java interop reference也要去(CTRL + F 「原始」)會有所幫助。

+0

非常感謝,我也有我的答案關於補貼問題==>「和數字原語將成爲數字,除非他們立即消耗的方法採取原語。」這解釋了簡單操作和一些不可能的taks(使用返回double/float /等方法擴展接口)的單獨性能有點差。 –