Non capisco il motivo per cui il codice seguente produce un avvertimento riflessione:Riflessione di avvertimento in codice generato da Clojure macro
(set! *warn-on-reflection* true)
(defmacro my-macro [k] `(.length ~(with-meta k {:tag String})))
(defn my-fun1 [k] (my-macro k))
;; Reflection warning, /tmp/form-init2370243866132870536.clj:1:18 - reference to field length can't be resolved.
Utilizzando macroexpand-1
mostra che il codice generato ha il typehint, e se scrivo lo stesso codice manualmente senza utilizzare una macro, non c'è alcun avviso riflessione:
(set! *print-meta* true)
(macroexpand-1 '(my-macro k))
;; (.length ^java.lang.String k)
(defn my-fun2 [k] (.length ^String k))
;; All good, no reflection warning
Analisi comparativa della funzione mostra che l'avviso non è solo una falsa pista, il riflesso si verifica effettivamente in fase di esecuzione:
(time (reduce + (map my-fun1 (repeat 1000000 "test"))))
;; "Elapsed time: 3080.252792 msecs"
(time (reduce + (map my-fun2 (repeat 1000000 "test"))))
;; "Elapsed time: 275.204877 msecs"
Quando eseguo la linea 'macroexpand-1', non vedo il tipo suggerimento. Penso che ci sia qualcosa di sbagliato nella macro, comunque; non accetta stringhe letterali: '(my-macro" pippo "); => java.lang.ClassCastException: java.lang.String non può essere lanciato su clojure.lang.IObj'. – Mars
Dovresti vedere il suggerimento sul tipo. Sei sicuro di aver impostato '* print-meta *' su vero? – noziar