is there something to do to get https://clojure.atlassian.net/browse/CLJ-1814 resolved anytime soon? This effects how libraries are being designed. Is there a good way / sample code how to resolve this properly in user space?
My use case is that I have ~5 core protocols in the lib (malli), need to check satisfies?
at creation time. With huge nested (real-life) schema inferring, this can take seconds. Was thinking of adding marker methods into protocols like -isSchema?
and implement the protocols for all things (`default` | Object
), but feels bad. Memoization with ConcurrentHashMap and weak references? Use meta-data to mark the created instances?
The entanglement with the metadata based instances makes things less straightforward there
The whole idea with protocols is to just make the call and let polymorphism sort it out - generally the need to call satisfies is a sign that something is off
Can you explain more why you need to check satisfies at creation time?
An example of what you proposed Alex can be found in Clojure Applied under Extending Protocols to Protocol
?
Also, could another approach be instead of making schema
a function make it part of a protocol, then add the different implementations for every case, i.e. every reify
for Schema and IntoSchema, extend to Object and to Vector?
A convenience in this case would be specifying default methods for protocols.
the Extending Protocols to Protocol
seems like a great match here. I actually didn’t realize that a static reify
creates just one class. Most of the schemas are implementes as -simple-schema
, and have a shared class:
(class (m/schema [:string {:title "a string"}]))
; => malli.core$_simple_schema$reify$reify__2320
(class (m/schema int?))
; => malli.core$_simple_schema$reify$reify__2320
(class (m/schema [:int {:min 1}]))
; => malli.core$_simple_schema$reify$reify__2320
Thanks both, I believe I can fix the perf issue with this, but voted also the issue.I can definitely bump this onto the radar for 1.11 though to think about
(Speaking about metadata: I'd like to bring https://clojure.atlassian.net/browse/CLJ-2568 to your attention as possibly interesting for 1.11 as well.)
here’s the culprit: https://github.com/metosin/malli/blob/master/src/malli/core.cljc#L993-L1010. It accepts a Schema
protocol instance, IntoSchema
protocol instance, a vector (the data syntax) or… anything. Schema
and IntoSchema
instances are implemented using reify
. All help appreciated here.
One helpful tool is to extend Object, and in it inspect the instance and then dynamically extend the protocol in the Object method for the newly understood concrete type. If all the instances are singletons via reify or metadata extension that won’t really help you
But if you have say multiple layers of protocols it works quite well
You only do the slow satisfies check once, after the dynamic extension the concrete type is known by the protocol and routes directly
I am aware
Interesting. thanks!
btw, if you want to vote, https://ask.clojure.org/index.php/3304/make-satisfies-as-fast-as-a-protocol-method-call has 0 votes right now