Yes, it does help out and prevent reflection. You can
(set! *warn-on-reflection* true) and see for yourself. Here’s why:
user=> (def expr (macroexpand-1 '(-> 10
(doto .next .next)
(.next (doto (.iterator (range 10)) .next .next))
user=> (first (last (second (last expr)))) ;; I did NOT get this right the first time :)
user=> (meta (first (last (second (last expr)))))
range symbol itself that has the metadata attached, which happens at read time, before macroexpansion.
-> does special work to reattach metadata only because it’s constructing its own new lists, and those lists might need to have metadata attached to them. In general, the idea of macros losing metadata usually hits us when we’re constructing new expressions based on old ones.
The type hint here doesn’t turn out to have much to do with macros, since we have :
user=> (.iterator (^clojure.lang.LazySeq range 10))
user=> (.iterator (range 10))
Reflection warning, NO_SOURCE_PATH:19:1 - reference to field iterator can't be resolved.
This means it’s a terrible example for showing how metadata gets preserved (which means it’s a bug in the book text), but the code itself is right in this case.
It gets worse, though! Clojure 1.7 and 1.8 both cause this example to fail with
ClassCastException clojure.lang.LongRange cannot be cast to clojure.lang.LazySeq :(
Thanks so much for the issue report, and also for the kinds words about the book. We’ll keep this issue in mind for future updates.