2012-10-07 30 views
5

我有試圖通過java.nio.file.WatchEvent<?>方式,通過Java代碼的一對夫婦層互操作(在這種情況下,java.nio.Path一些Clojure的代碼:如何在線程( - >)宏中鍵入提示?

(defn unroll-event 
    [^WatchEvent event] 
    { :kind (.kind event) 
    :context (.context event) 
    :path (-> event .context .toAbsolutePath .toString)}) 

在這段代碼中,我有一個類型暗示event,所以我會認爲它應該能夠找出什麼.context應該返回,因此,能夠找出什麼.toAbsolutePath.toString做。我認爲在這種情況下,因爲.context被定義已返回一個通用類型T,I我想知道如果我可以鍵入提示.context的電話。我已經試過了prependin摹^java.nio.file.Path.context,和^Path^String.toAbsolutePathtoString,分別,但我仍然得到警告:

Reflection warning, junkcode/core.clj:28 - reference to field toAbsolutePath can't be resolved. 
Reflection warning, junkcode/core.clj:28 - reference to field toString can't be resolved. 

有什麼我可以在這種情況下怎麼辦?是因爲->是一個宏,並且在那裏有特別的類型提示規則嗎?

+0

這是什麼擴大到?使用'clojure.walk/macroexpand-all' – noahlz

回答

2

(-> x .blah ^String .bar)擴展到,基本上,(^String .bar (.blah x)),這顯然不是你想要的提示。重點在於type-hinting在任何上下文(例如宏)中都沒有特殊的行爲:它只是應用於源代碼符號的元數據。在你的示例->中,沒有地方可以將元數據放在輸入表單上,這會導致它在輸出表單中成爲你想要的位置。因此,您需要編寫其他表單,例如(-> ^Path (.context event) .toAbsolutePath str)。另外,Clojure的推理器不知道泛型類型的任何內容,所以方法返回的T被視爲方法返回的對象,這就解釋了爲什麼你需要在這裏提示。

0

我不知道這是否一直如此,但在Clojure 1.4.0,1.5.1和1.6.0中,只要使用圓括號,就可以在->中的任意點鍵入提示:

user=> (set! *warn-on-reflection* true) 
true 
user=> (fn [^java.nio.file.WatchEvent e] 
     (-> e ^java.nio.file.Path .context .toAbsolutePath)) 
Reflection warning, /private/var/folders/9_/wdph6m796zzc8trzcbtcmhrn5bjpt0/T/form-init8364673644863044068.clj:1:35 - reference to field toAbsolutePath on java.lang.Object can't be resolved. 
#<user$eval1995$fn__1996 [email protected]> 
user=> ; but no warning if we do 
user=> (fn [^java.nio.file.WatchEvent e] 
     (-> e ^java.nio.file.Path (.context) .toAbsolutePath)) 
#<user$eval1999$fn__2000 [email protected]> 

唯一的區別是在.context左右的parens。