Fork me on GitHub
#pedestal
<
2020-06-28
>
husayn16:06:42

is it possible to extend a protocol defined in another library ? …. specifically TraceSpan in io.pedestal.log so that it implements .Closeable ?

emccue18:06:18

no, but you can make your own protocol to bridge the two

emccue18:06:46

(defprotocol AsCloseable
  (-as-closeable [_]))

(extend-type java.io.Closeable
  AsCloseable
  (-as-closeable [this] this))

emccue18:06:11

actually, err

emccue18:06:54

its not super straight forward

emccue18:06:25

you can't actually implement a protocol on something based on it implementing another protocol

emccue18:06:14

if you want to do that you probably would have to do a custom dispatch mechanism in some way

emccue18:06:09

(defn as-closeable [item]
  (cond
    (satisfies? TraceSpan (type item))
    (...)
   
    (implements? Closeable item)
    item

    :else
    ...AAAA...))

emccue18:06:22

the simplest and least extensible way would be this

emccue18:06:11

i actually consider this a pretty big downside to protocols - they don't actually work like traits in rust or similar where you can implement a trait for anything that implements a trait

emccue19:06:42

(def extending-protocols (atom [])

(defn register-impl-for-protocol! [protocol impl]
  (swap! extending-protocols conj [protocol impl]))

(defn as-closeable [item]
  (cond
    (instance? Closeable item)
    item

    :else
    (loop [impls @extending-protocols]
      (if-not (empty? impls)
        (let [[protocol impl] (first impls)
              remaining-impls (rest impls)]
          (if (satisfies? protocol item)
            (impl item)
            (recur remaining-impls)))
        (throw (IllegalArgumentException. (str "No Impl found for " item)))))

emccue19:06:05

the downside here is that with-open and co won't actually work

emccue19:06:11

I actually made a thing that I think came close to giving a general approach for this before