Which protocol defines conj in clojure?

Let me say I wrote a function:

(defn foo [to x] (conj to x)) 

And hope to record it by declaring that certain protocols must be implemented (for example, the structure/type must support calling conj). Is there a website or database that contains this information? Obviously, I want to summarize this question as “Where can I find a complete reference for all clojure protocols?”

As a clear and specific example of using Sam Estep’s suggestion, it looks like:< /p>

(defn invert-many-to-one
"returns a one-to-many mapping where vals are collections of type `(constructor-fn)`,< br /> (defaults to `hash-set`). Note that `constructor-fn` is a function of 0 args.
`insert-fn` function can be passed. if only `constructor-fn` is passed
then `insert-fn` defaults to `conj` and `(constructor-fn)` must be an instance
of `clojure.lang.IPersistentCollection`"
([m] (invert -many-to-one hash-set conj m))
([constructor-fn m] {:pre [(instance? clojure.lang.IPersistentCollection (constructor-fn))]}
(invert -many-to-one constructor-fn conj m))
([constructor-fn insert-fn m]
(persistent!
(reduce (fn [m [kv]]
(assoc! mv (insert-fn (clojure.core/get mv (constructor-fn)) k)))
(transient ()) m))))

< div class="content-split">

Unfortunately, protocols were not introduced until Clojure 1.2. By that time, all the built-in data structure abstractions have been implemented as Java interfaces instead of protocols. This has the disadvantages you expect, but when re-implementing all these abstractions as protocols Suitable for ClojureScript because it was created after the protocol was introduced, and it is not feasible to improve them into JVM Clojure.

If you look at the source code of conj, you You will see that it calls clojure.lang.RT/conj, which requires its first parameter to implement the IPersistentCollection interface. Therefore, you can write the function like this:

(defn foo [to x]
{:pre [(instance? clojure.lang.IPersistentCollection to)]}
(conj to x))

For the sake of generalization, I would like to point out a question, I have asked questions about implementing the core interface of Clojure in the past. If the answer is not enough to solve your problem, please let me know and I will add more details here Information.

I will make some small adjustments to your invert many-to-one function:

(defn invert-many-to-one< br /> "Returns a one-to-many mapping where vals are collections of type
`(constructor-fn)` (defaults to `hash-set`). Note that `constructor-fn` is a
function of 0 args. `insert-fn` function can be passed. If only
`constructor-fn` is passed then `insert-fn` defaults to `conj`.
`(constructor- fn)` must be an instance of
`clojure.lang.IPersistentCollection`."
([m ]
(invert-many-to-one hash-set m))
([constructor-fn m]
(invert-many-to-one constructor-fn conj m))< br /> ([constructor-fn insert-fn m]
{:pre [(instance? clojure.lang.IPersistentCollection (constructor-fn))]}
(persistent!
(reduce (fn [m [kv]]
(assoc! mv (insert-fn (get mv (constructor-fn)) k)))
(transient ()) m))))

> I changed the arity-1 body and called it arity-2 body instead of arity-3 body; this way, you only specify conj as the default value in one place.
>I moved the precondition to arity-3 in order to use it in all situations.
>I replaced clojure.core/get, just to get the idiom.

Of course, as you pointed out in the comments , These three changes have their own shortcomings, so be sure to bring them.

Let me say I wrote a function:

(defn foo [to x] (conj to x))

And hope to record it by declaring that some protocol must be implemented (such as in the structure/type must Support calling conj). Is there a website or database that contains this information? Obviously, I want to summarize this question as "Where can I find a complete reference for all clojure protocols?"

As a clear and specific example of using Sam Estep's suggestion, it looks like:< /p>

(defn invert-many-to-one
"returns a one-to-many mapping where vals are collections of type `(constructor-fn)`,< br /> (defaults to `hash-set`). Note that `constructor-fn` is a function of 0 args.
`insert-fn` function can be passed. if only `constructor-fn` is passed
then `insert-fn` defaults to `conj` and `(constructor-fn)` must be an instance
of `clojure.lang.IPersistentCollection`"
([m] (invert -many-to-one hash-set conj m))
([constructor-fn m] {:pre [(instance? clojure.lang.IPersistentCollection (constructor-fn))]}
(invert -many-to-one constructor-fn conj m))
([constructor-fn insert-fn m]
(persistent!
(reduce (fn [m [kv]]
(assoc! mv (insert-fn (clojure.core/get mv (constructor-fn)) k)))
(transient ()) m))))

< p>

Unfortunately, protocols were not introduced until Clojure 1.2. By then, all the built-in data structure abstractions have been Implemented as Java interfaces instead of protocols. This has the disadvantages you expect, but when re-implementing all these abstractions as a protocol is suitable for ClojureScript, because it was created after the protocol was introduced, it is not feasible to improve them into JVM Clojure .

If you look at the source code of conj, you will see that it calls clojure.lang.RT/conj, which requires the first One parameter implements the IPersistentCollection interface. Therefore, you can write a function like this:

(defn foo [to x]
{: pre [(instance? clojure.lang.IPersistentCollection to)])
(conj to x))

For the sake of generalization, I want to point out a question, I have asked about implementing Clojure core in the past The problem of the interface. If the answer is not enough to solve your problem, please let me know and I will add more details here.

I will do some small work on your reverse many-to-one function Adjustment:

(defn invert-many-to-one
"Returns a one-to-many mapping where vals are collections of type
`( constructor-fn)` (defaults to `hash-set`). Note that `constructor-fn` is a
function of 0 args. `insert-fn` function can be passed. If only
` constructor-fn` is passed then `insert-fn` defaults to `conj`.
`(constructor-fn)` must be an instance of
`clojure.lang.IPersistentCollection`."
([m]
(invert-many-to-one hash-set m))
([constructor -fn m]
(invert-many-to-one constructor-fn conj m))
([constructor-fn insert-fn m]
{:pre [(instance? clojure. lang.IPersistentCollection (constructor-fn))])
(persistent!
(reduce (fn [m [kv]]
(assoc! mv (insert-fn (get mv (constructor- fn)) k)))
(transient ()) m))))

>I changed the arity-1 body and called it arity-2 body instead of arity-3 body ; This way, you only specify conj as the default value in one place.
>I moved the precondition to the arity-3 body so that it can be used in all situations.
>I replaced clojure.core/get , Just to get idioms.

Of course, as you pointed out in the comments, these three changes have their own shortcomings, so be sure to bring them.

Leave a Comment

Your email address will not be published.