Is there a way to turn off or ignore *warn-on-reflection*` for a particular code segment? My use-case is that if I don't know the type of a value, using reflection is probably more efficient than writing a cond to check the type, but I also don't want the reflection warning popping up all the time.
I do it like this:
(set! *warn-on-reflection* false)
;; code
(set! *warn-on-reflection* true)(or if you don't want true, capture the old value first and then restore that one)
If it's a library though... I guess I'd need to do something like:
(def warn-on-reflection *warn-on-reflection*)
(def *warn-on-reflection* false)
...
(def *warn-on-reflection* warn-on-reflection)I daresay I can't use a binding for this because it needs to be a top-level form, as that's the unit of compilation.
if it's a library it's still fine to put it to true, it won't affect other namespaces
that's correct
https://github.com/clj-commons/hickory/commit/faf4a95143c3109692e2d5747e722088d8540e08
Wait, it won't affect other namespaces? Why?
because every time a namespace is compiled, it's re-bound to the original value
similar to *ns*
Ohh.. Huh. I didn't know that. I guess Leiningen must inject it into namespaces when they're loaded, or use some sort of command line switch.
you can affect the root binding , e.g. using alter-var-root in user.clj
but as long as you don't do that, you're fine
Ah, and then the compiler will use that as the default.
right
Thanks for all the help - it's very much appreciated.
I'm not sure reflection is faster than cond over instance of checks
I think you might be right; I've just run a few checks to confirm, and instance checking seems to be faster, which I'm surprised by.
I think reflection is more open ended. But a conditional on instance of is more local and closed so it can probably be optimized more easily.
class checking and downcasting is extremely fast because you're basically doing an enum check, whereas reflection requires you lookup a substantial data structure that isn't usually gonna be in cache and iterate over it before eventually finding the right method, doing some validation, and then jumping to the body.
My assumption was that there'd be some optimisation around partial reflection. i.e. if the compiler knows there's only three possible results given the types it knows, it can optimise the lookup. I guess that's not a common scenario in Java, though.
as far as I understand clojure reflective calls are close to a naive implementation, largely amounting to calling getMethods on the target class and iterating through the methods until a valid one is found (with plenty of class hierarchy checks and array allocations along the way).
I'm curious: Why turn it off it in a library? Why not convey to the user that reflection is happening?
isn't the purpose of a warning that you perhaps missed something and want to take action on it? in this case you are completely aware of reflection and don't want to be warned about it?
you could also insert the call to clojure.lang.Reflector yourself btw, to bypass the warning
I'm usually not aware of everything happening in libraries, and if I want to turn it off for some library call I can do it myself. I'd be surprised to find a code that turns off what I consider a user setting in a library
> and if I want to turn it off for some library call I can do it myself. warn on reflection doesn't happen during calls, it happens during compilation
so wrapping the call with (def *warn-on-reflection* false) ... won't work?
no it is a compilation thing, not a runtime thing
anyway intuitively I'd still want to be able to control it somehow
something like
(def warn-on-reflection *warn-on-reflection*)
(def *warn-on-reflection* (or *library-config-var*
*warn-on-reflection*))
...
(def *warn-on-reflection* warn-on-reflection)well, it won't work with booleans, but you get the point 🙂
A library author can still just write something like this:
(clojure.lang.Reflector/invokeInstanceMethod "hello" "length" (into-array []))
and you won't get a warning.And even if you detected that reflection was happening in a library what were you going to do about it as a user? send a PR?
For me the point is that I'd know about it. And maybe the compiler can optimize them some day, but it won't optimize java reflection calls, so I guess they're not going away
anyway it's straying off topic, I was curious about this behavior
There's a more accurate way to detect reflection, even from clojure.lang.Reflector etc, which is using a java agent, see e.g. https://www.graalvm.org/jdk21/reference-manual/native-image/dynamic-features/Reflection/
that's how I found this one: https://github.com/clojure/clojure/commit/69387c5e7d617ebe17ebaaa97344a1bb6a5f0817
> i.e. if the compiler knows there's only three possible results given the types it knows Reflection is enumerating methods at runtime; given the JVM execution model there isn't really a way for the compiler to know the set of methods that will be available at runtime, as the classpath may be different (as well as the base JVM version).
I understand the intuition of not wanting libraries to turn off the warning. I've had scenarios where you bang your head on why some piece of code is so slow, only to start looking into a library and realizing it's using reflection and that's why.
Though often it was closure core itself 😂, and since that's AOT compiled you don't get warned.