clojure-dev

Issues: https://clojure.atlassian.net/browse/CLJ | Guide: https://insideclojure.org/2015/05/01/contributing-clojure/
2020-01-13T22:09:56.007200Z

Am I correct in believing that derive , parents , and ancestors in clojure.core have no relationship with protocols?

bronsa 2020-01-13T22:10:14.007700Z

yup

2020-01-13T22:11:53.008600Z

And if the answer is "yes", is there anything built into Clojure that is like parents or ancestors that takes protocols into account? (Or if that would be ill-defined or not make sense for some reason, would appreciate some hints as to why)

bronsa 2020-01-13T22:13:25.009400Z

no, protocols have no hierarchy semantics by design

2020-01-13T22:14:10.010200Z

Even if no hierarchy, something like "what protocols does this class/interface implement?" could be useful to query, perhaps?

bronsa 2020-01-13T22:14:48.011200Z

but it's not possible to do, protocol implementations belong to the protocol not to the classes/interfaces

bronsa 2020-01-13T22:15:06.012Z

you'd have to scan the open universe of protocols to know which ones a class extends

2020-01-13T22:16:28.013700Z

In Clojure/Java, I have forgotten which ways of defining an implementation of a protocol do this, but some create a "class/interface extends Java-interface-of-protocol" relationship. Those can be seen via Java reflection API, and so also parents and ancestors . Double checking that to make sure I am not imagining things.

bronsa 2020-01-13T22:17:05.014400Z

yes, that happens when you implement a protocol inline in a deftype

bronsa 2020-01-13T22:17:15.014900Z

but it's merely an optimisation/implementation detail

bronsa 2020-01-13T22:17:33.015900Z

and crucially it's not a thing that happens in all the ways a type can extend a protocol

2020-01-13T22:18:11.017Z

Understood. I was a bit confused when I first came across that. It does mean some of those relationships show up in parents results, but not all, I think.

ghadi 2020-01-13T22:18:25.017300Z

there is preference within protocols impls already: protocol extensions to concretions win over extensions to interfaces

bronsa 2020-01-13T22:19:55.018100Z

are you talking about extend with meta?

bronsa 2020-01-13T22:20:19.018400Z

oh nvm I understand what you mean

ghadi 2020-01-13T22:21:29.020100Z

rephrased for broadcast: checking for a protocol implementation walks up the concrete hierarchy before the interfaces

2020-01-13T22:21:46.020600Z

I am still catching up, though 🙂 Ghadi, do you mean that if class A has an implementation for protocol P, and class A implements interface I1, and I1 has an implementation for protocol P, then calling a protocol P function on an instance of class A should always execute the class A implementation?

ghadi 2020-01-13T22:22:21.020800Z

yes

2020-01-13T22:23:18.022600Z

But still, if one was creating a "does X implement/extend Y" kind of diagram, "A implements P" is true in that situation, regardless of exactly which implementation of P is used.

ghadi 2020-01-13T22:24:22.023900Z

right -- sorry I thought the original question was about preference when there is ambiguity

2020-01-13T22:24:29.024100Z

So there is no central "registry" of protocols in Clojure, but if you had a list of namespaces, you could walk through all of their Vars and look for them, based on knowing what protocols "look like" in the implementation details?

bronsa 2020-01-13T22:24:46.024700Z

(note that in the case of multiple inheritance w/o a clear derivation preference, it's undefined which impl will be used)

bronsa 2020-01-13T22:25:11.026Z

@andy.fingerhut yes, but at a specific point in time

2020-01-13T22:25:12.026100Z

I don't mind the extra detail, but I was more asking whether there is already something like parents that, given A, would return P among the results, if A implements P

bronsa 2020-01-13T22:25:25.026500Z

protocols can be extended a runtime

bronsa 2020-01-13T22:25:40.027400Z

at t1 class A can not extend protocol P but at t2 it may

2020-01-13T22:25:47.027700Z

Well, Java classes can be loaded at runtime, too, so runtime changes don't bother me 🙂

ghadi 2020-01-13T22:26:15.028600Z

I'm going to split hairs here @bronsa: the undefined impl case you're talking about is when you implement multiple interfaces to which the protocol is extended

âž• 1
2020-01-13T22:26:23.028800Z

Ah, I guess you mean that Java classes have their extends/implements-Java-interfaces relationships all known after the class is initialized, but protocols have another level of dynamicity beyond that?

bronsa 2020-01-13T22:26:49.029100Z

yep

2020-01-13T22:28:13.031200Z

Thanks for the clarification there. FYI, the reason for my asking is that I was hoping to enhance Stuart Sierra's class-diagram library to show "implements protocol" relationships, in addition to the parents / ancestors relationships that it shows now, and trying to figure out how.

bronsa 2020-01-13T22:29:34.033100Z

i'm sure for tooling purposes it should be easy to get something working even tho it may not be correct/complete 100% of the cases

2020-01-13T22:29:43.033500Z

Among other enhancements that led me to look up 1970s CS algorithms papers on computing transitive reductions, which is something I've almost known how to do, but never in anger yet.

2020-01-13T22:30:41.034200Z

These diagrams can get visually messy pretty quickly.

2020-01-13T22:43:37.036200Z

No need for anyone to dig through lots of code, but as a semi-quick hack, looking through all Vars in a namespace for those whose value is a Clojure map, that contains at least the keys (:on :on-interface :sigs :var :method-map :method-builders) , seems likely to catch everything defined via Clojure/Java defprotocol , and while it could possibly catch other things, that seems somewhat unlikely to happen.

2020-01-13T22:44:02.036700Z

I could do additional sanity checks on the types/values associated with those keys, of course.

ghadi 2020-01-13T22:44:37.037200Z

:impls too

ghadi 2020-01-13T22:44:50.037800Z

if you don't see :impls that means the protocol has no extenders

2020-01-13T22:45:11.038200Z

I did a quick check, and :doc and :impls are not there when one first defines a protocol, but understood, yes.

2020-01-13T22:46:28.038700Z

And it does not gain a key :impls if one creates a deftype that implements the protocol.

ghadi 2020-01-13T23:04:18.040300Z

yup, the extenders of an interface are an open set. (e.g. functions that return a reify)

ghadi 2020-01-13T23:04:22.040500Z

@andy.fingerhut

2020-01-13T23:06:01.041700Z

Thanks for that info. For the purposes of this exercise I am going through, I am looking only for protocols that a given Java class/interface implements, not necessarily all Java objects that currently exist that implement them.