clojure-dev

Issues: https://clojure.atlassian.net/browse/CLJ | Guide: https://insideclojure.org/2015/05/01/contributing-clojure/
ikitommi 2020-10-25T15:39:06.137800Z

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?

ikitommi 2020-10-25T15:47:11.143300Z

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?

alexmiller 2020-10-25T15:58:16.144500Z

The entanglement with the metadata based instances makes things less straightforward there

alexmiller 2020-10-25T15:59:32.146Z

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

alexmiller 2020-10-25T16:00:04.146700Z

Can you explain more why you need to check satisfies at creation time?

Ben Sless 2020-10-26T07:46:35.154800Z

An example of what you proposed Alex can be found in Clojure Applied under Extending Protocols to Protocol?

Ben Sless 2020-10-26T07:49:31.155Z

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.

ikitommi 2020-10-26T10:12:58.155300Z

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.

alexmiller 2020-10-25T16:00:53.147400Z

I can definitely bump this onto the radar for 1.11 though to think about

borkdude 2020-10-25T16:03:36.147900Z

(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.)

ikitommi 2020-10-25T16:31:50.148100Z

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.

alexmiller 2020-10-25T18:28:49.151900Z

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

alexmiller 2020-10-25T18:29:28.152600Z

But if you have say multiple layers of protocols it works quite well

alexmiller 2020-10-25T18:30:58.153800Z

You only do the slow satisfies check once, after the dynamic extension the concrete type is known by the protocol and routes directly

alexmiller 2020-10-25T18:31:55.154200Z

I am aware

ikitommi 2020-10-25T19:12:01.154300Z

Interesting. thanks!

alexmiller 2020-10-25T19:41:29.154500Z

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