Nie rozumiem dlaczego poniższy kod generuje ostrzeżenie refleksji:ostrzeżenie Odbicie w kodzie generowane przez Clojure makro
(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.
Korzystanie macroexpand-1
pokazuje, że wygenerowany kod nie mają typehint, a jeśli piszę to samo Kod ręcznie bez użycia makra, nie ma ostrzeżenia odbicie:
(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
benchmarking funkcji pokazuje, że ostrzeżenie to nie tylko czerwony śledź, odbicie w rzeczywistości występuje w czasie wykonywania:
(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"
Kiedy uruchomić linię 'macroexpand-1', nie widzę typ Wskazówka. Myślę jednak, że coś jest nie tak z makrem; nie przyjmuje łańcuchów literowych: '(my-macro" foo "); => java.lang.ClassCastException: java.lang.String nie może być rzutowany na clojure.lang.IObj'. – Mars
Powinieneś zobaczyć wskazówkę dotyczącą typu. Czy na pewno ustawisz "* print-meta *" na wartość true? – noziar