2012-10-07 8 views
5

私はjava.nio.file.WatchEvent<?>の仕方によってjava.nio.Path、この場合には(Javaコードのカップルの層を貫通して相互運用しようとしているいくつかのClojureのコードを持っています。このコードではスレッド( - >)マクロ内にヒントを入力するにはどうすればよいですか?

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

、私はタイプがeventを示唆しているので、私は希望それはでなければなりません.contextが何を返すのか分かり、それで、.toAbsolutePath.toStringが何をするのか分かります。この場合、.contextが定義されているので、T私が.contextへの呼び出しをヒントに入力できるかどうか疑問に思っています。私はちょうどprependin .contextにグラム^java.nio.file.Path、および.toAbsolutePathtoStringから^Path^String、それぞれが、私はまだ警告を得る:

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))に展開されていますが、これは明らかにヒントが必要な場所ではありません。要点は、タイプヒントはどのようなコンテキスト(マクロなど)でも特別な動作をしないということです。ソースコードに適用されたメタデータだけです。あなたの例では、->には、入力フォームにメタデータを置くことができる場所がないため、出力フォームに必要な場所になります。したがって、例えば(-> ^Path (.context event) .toAbsolutePath str)のような他の形式を書く必要があります。

また、Clojureの推論者はジェネリック型について何も知らないので、メソッドを返すTはメソッド返すObjectとして扱われ、ここですべてのことをヒントする必要がある理由が説明されます。

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です。

関連する問題