2012-10-07 8 views
5

ho un po 'di codice Clojure che sta cercando di interoperabilità attraverso un paio di strati di codice Java (in questo caso, java.nio.Path attraverso java.nio.file.WatchEvent<?>:Come si può digitare un suggerimento all'interno della macro di threading (->)?

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

In questo codice, ho tipo accennato event, quindi vorrei Penso che dovrebbe essere in grado di capire che cosa .context deve restituire, e come tale, essere in grado di capire cosa .toAbsolutePath e .toString fanno. credo che in questo caso, dal momento che .context è definito è la restituzione di un tipo generico T, ho mi chiedo se posso digitare suggerire la chiamata a .context. Ho provato solo prima g ^java.nio.file.Path-.context, e ^Path e ^String-.toAbsolutePath e toString, rispettivamente, ma ho ancora ottenere gli avvertimenti:

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. 

C'è qualcosa che posso fare in questo caso? È perché -> è una macro e ci sono regole speciali per il tipo di suggerimento al suo interno?

+0

A cosa si sta espandendo? Usa 'clojure.walk/macroexpand-all' – noahlz

risposta

2

(-> x .blah ^String .bar) si espande in, fondamentalmente, (^String .bar (.blah x)), che chiaramente non è dove si desidera il suggerimento. Il punto è che il tipo di suggerimento non ha un comportamento speciale in nessun contesto (ad es. Macro): sono solo i metadati applicati ai simboli del codice sorgente. Nell'esempio ->, non è possibile inserire metadati nel modulo di input che causerà la posizione desiderata nel modulo di output. Quindi è necessario scrivere qualche altro modulo, ad esempio (-> ^Path (.context event) .toAbsolutePath str).

Inoltre, l'inferenza di Clojure non conosce nulla sui tipi generici, quindi un metodo-return-T viene trattato come un metodo-return-Object, il che spiega il motivo per cui è necessario suggerire del tutto qui.

0

Non so se questo è sempre stato il caso, ma in Clojure 1.4.0, 1.5.1 e 1.6.0, è possibile digitare hint in qualsiasi punto in -> finché si utilizzano le parentesi:

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]> 

L'unica differenza è il paren intorno a .context.

Problemi correlati