<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Clojure Q&amp;A - Recent questions tagged protocol</title>
<link>https://ask.clojure.org/index.php/tag/protocol</link>
<description></description>
<item>
<title>Implement ^:async (CLJS) for protocol functions and multi-methods</title>
<link>https://ask.clojure.org/index.php/15187/implement-async-cljs-for-protocol-functions-multi-methods</link>
<description>&lt;p&gt;In ClojureScript (as of &lt;code&gt;1.12.145&lt;/code&gt;) one can declare a function (&lt;code&gt;defn&lt;/code&gt;, &lt;code&gt;fn&lt;/code&gt;) to be async by adding the metadata &lt;code&gt;^:async&lt;/code&gt;. However, the same is not applicable to protocol functions and multi-methods. Since async is an invocation semantic, should it be carried over to protocol functions and multimethods? (If yes, should it apply to the protocol definition in &lt;code&gt;defprotocol&lt;/code&gt; or to the protocol implementation in &lt;code&gt;reify&lt;/code&gt;?)&lt;/p&gt;
&lt;p&gt;If async is not to be allowed in protocol functions and multimethods, then the documentation should clearly mention the omissions, alternatives and workaround.&lt;/p&gt;
</description>
<category>ClojureScript</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15187/implement-async-cljs-for-protocol-functions-multi-methods</guid>
<pubDate>Sun, 19 Jul 2026 11:53:45 +0000</pubDate>
</item>
<item>
<title>Accidentally specifying a protocol multiple times in deftype may omit some method implementations</title>
<link>https://ask.clojure.org/index.php/13419/accidentally-specifying-protocol-multiple-implementations</link>
<description>&lt;p&gt;If you accidentally specify a protocol multiple times in a deftype form, some method implementations of that protocol may be omitted.&lt;/p&gt;
&lt;p&gt;Repro: &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defprotocol P (f [this]) (g [this]))

(deftype T []
  P
  (f [this] :F)
  P
  (g [this] :G))

(def t (-&amp;gt;T))

(f t)
;; Execution error (AbstractMethodError) at user/eval187 (REPL:1).
;; Receiver class user.T does not define or inherit an implementation of the resolved method 'abstract java.lang.Object f()' of interface user.P.

(g t) ;=&amp;gt; :G
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can confirm by macroexpanding the deftype form that some of the method implementations are ignored:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(macroexpand '(deftype T [] P (f [this] :F) P (g [this] :G)))
;=&amp;gt; (let* [] (deftype* user/T user.T [] :implements [user.P clojure.lang.IType] (g [this] :G)) (clojure.core/import user.T) (clojure.core/defn -&amp;gt;T &quot;Positional factory function for class user.T.&quot; [] (new user.T)) user.T)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It seems like the root cause boils down to &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/clojure/blob/08a2d9bdd013143a87e50fa82e9740e2ab4ee2c2/src/clj/clojure/core_deftype.clj#L46-L51&quot;&gt;&lt;code&gt;parse-impls&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(#'clojure.core/parse-impls '(P (f [this] :F) P (g [this] :G)))
;=&amp;gt; {P ((g [this] :G))}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In my opinion, it would be nice if deftype would check to see if the same protocol is specified more than once and throw an error if so. Otherwise the method implementations should not be ignored without any warning, I think.&lt;/p&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/13419/accidentally-specifying-protocol-multiple-implementations</guid>
<pubDate>Tue, 31 Oct 2023 21:46:44 +0000</pubDate>
</item>
<item>
<title>Should extenders also list types that extend a protocol via deftype?</title>
<link>https://ask.clojure.org/index.php/11680/should-extenders-also-list-types-that-extend-protocol-deftype</link>
<description>&lt;p&gt;I was playing around with protocols at the REPL and encountered the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defprotocol IGreeter
  (greet [this]))

(deftype MyGreeter []
  IGreeter
  (greet [_] &quot;hi from MyGreeter&quot;))

(extends? IGreeter MyGreeter)
;=&amp;gt; true

 ;; I expected to see MyGreeter listed here, but result is nil
(extenders IGreeter)
;=&amp;gt; nil
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now extend the protocol to a few types.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(extend-protocol IGreeter 
  String 
  (greet [this] &quot;hi-string&quot;)
  clojure.lang.Symbol 
  (greet [this] 'hi-sym)  ; ' help syntax highlighter
  clojure.lang.Keyword
  (greet [this] :hi-kw))

(extenders IGreeter)
;=&amp;gt; (java.lang.String clojure.lang.Symbol clojure.lang.Keyword)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;String, Symbol and Keyword show up as extenders of IGreeter. MyGreeter does not. This was especially surprising since (extends? IGreeter MyGreeter) returns true.  Am I misunderstanding something or could this be a bug? Thank you!&lt;/p&gt;
</description>
<category>Protocols</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/11680/should-extenders-also-list-types-that-extend-protocol-deftype</guid>
<pubDate>Fri, 25 Mar 2022 19:01:40 +0000</pubDate>
</item>
<item>
<title>How should I correctly detect a protocol symbol in a macro targeting CLJS?</title>
<link>https://ask.clojure.org/index.php/10731/should-correctly-detect-protocol-symbol-macro-targeting-cljs</link>
<description>&lt;p&gt;Up through Clojurescript 1.10.844, I could reliably tell whether a symbol &lt;code&gt;sym&lt;/code&gt; (at macro-expansion time) referred to a protocol by examining the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(:protocol-symbol (cljs.analyzer.api/resolve &amp;amp;env sym))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As of the &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/clojurescript/commit/a8422ee060d7d98f7578c9acb2824a5e346e7958&quot;&gt;commit for CLJS-3276&lt;/a&gt;, this no longer works in my code. As far as I can tell, &lt;code&gt;defprotocol&lt;/code&gt; still attaches this data, and cljs.core &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/clojurescript/blob/ac23fec265bdf0ca971eb35c16da4b59191da5ca/src/main/clojure/cljs/core.cljc#L1421&quot;&gt;still uses this method internally&lt;/a&gt;. Is there a better / supported way to detect whether a symbol refers to a protocol? I'm very much hoping that this behavior is reintroduced, or else that there is some other reliable method.&lt;/p&gt;
</description>
<category>ClojureScript</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/10731/should-correctly-detect-protocol-symbol-macro-targeting-cljs</guid>
<pubDate>Fri, 25 Jun 2021 00:03:30 +0000</pubDate>
</item>
<item>
<title>Better stacktraces for protocol methods</title>
<link>https://ask.clojure.org/index.php/9775/better-stacktraces-for-protocol-methods</link>
<description>&lt;p&gt;Currently extend-protocol-defined functions look like this in the stacktrace:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;at app.core$eval3547$fn__3548.invoke(core.clj:23)
at app.core$eval3522$fn__3523$G__3513__3532.invoke(core.clj:14)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Needless to say these aren't exactly descriptive. Not to mention the lines it refers to are where extend-protocol and defprotocol were called, not where the function definition is.&lt;/p&gt;
&lt;p&gt;I'd hope for something like &lt;code&gt;app.core/MyProtocol/IfaceImplemented/function_name_1234&lt;/code&gt; with the line number where the &quot;offending&quot; piece of code is, not the definition.&lt;/p&gt;
&lt;p&gt;I hacked at it a little locally and found that changing emit-method-builder, emit-impl and emit-hinted-impl a little made the stacktraces much more readable.&lt;/p&gt;
&lt;p&gt;Hack diff:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;diff --git a/src/clj/clojure/core_deftype.clj b/src/clj/clojure/core_deftype.clj
index 786f0d4b..73570dbf 100644
--- a/src/clj/clojure/core_deftype.clj
+++ b/src/clj/clojure/core_deftype.clj
@@ -586,9 +586,10 @@
 
 (defn- emit-method-builder [on-interface method on-method arglists extend-via-meta]
   (let [methodk (keyword method)
-        gthis (with-meta (gensym) {:tag 'clojure.lang.AFunction})
-        ginterf (gensym)]
-    `(fn [cache#]
+        gthis (with-meta (gensym (str method)) {:tag 'clojure.lang.AFunction})
+        ginterf (gensym)
+        giface-name (gensym (last (.split (name on-interface) &quot;\\.&quot;)))]
+    `(fn ~giface-name [cache#]
        (let [~ginterf
              (fn
                ~@(map 
@@ -812,9 +813,21 @@
                    (:var proto)))))
     (-reset-methods (alter-var-root (:var proto) assoc-in [:impls atype] mmap))))
 
+(defn- iface-fn-name
+  ([p f]
+   (iface-fn-name &quot;&quot; p f))
+  ([c p f]
+   (let [c-name (cond
+                  (symbol? c)
+                    (last (.split (name c) &quot;\\.&quot;))
+                  (nil? c)
+                    &quot;nil&quot;
+                  :else nil)]
+     (symbol (str p (when c-name (str &quot;__&quot; c-name)) (first f))))))
+
 (defn- emit-impl [[p fs]]
   [p (zipmap (map #(-&amp;gt; % first keyword) fs)
-             (map #(cons `fn (drop 1 %)) fs))])
+             (map #(cons `fn (cons (iface-fn-name p %) (drop 1 %))) fs))])
 
 (defn- emit-hinted-impl [c [p fs]]
   (let [hint (fn [specs]
@@ -826,7 +839,7 @@
                               body))
                       specs)))]
     [p (zipmap (map #(-&amp;gt; % first name keyword) fs)
-               (map #(cons `fn (hint (drop 1 %))) fs))]))
+               (map #(cons `fn (cons (iface-fn-name c p %) (hint (drop 1 %)))) fs))]))
 
 (defn- emit-extend-type [c specs]
   (let [impls (parse-impls specs)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Logs after:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;at app.core$eval3965$ProtocolName__ClassName__FnName__3966.invoke(core.clj:23)
at app.core$eval3940$ProtocolName3932__3941$__FnName3930__3950.invoke(core.clj:14)
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Protocols</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/9775/better-stacktraces-for-protocol-methods</guid>
<pubDate>Tue, 10 Nov 2020 05:30:20 +0000</pubDate>
</item>
<item>
<title>Why does an atom not implemented the &quot;ISwap&quot; protocol?</title>
<link>https://ask.clojure.org/index.php/9291/why-does-an-atom-not-implemented-the-iswap-protocol</link>
<description>&lt;p&gt;Why does an atom &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/core.cljs#L4431-L4458&quot;&gt;not implemented&lt;/a&gt; the &quot;ISwap&quot; protocol?  &lt;/p&gt;
&lt;p&gt;It's the &lt;code&gt;swap!&lt;/code&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/clojurescript/blob/master/src/main/cljs/cljs/core.cljs#L4510-L4530&quot;&gt;implementation&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defn swap!
  ([a f]
   (if (instance? Atom a)
     (reset! a (f (.-state a)))
     (-swap! a f))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It's not about optimization because GCC does not inline the &lt;code&gt;swap!&lt;/code&gt; call.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;;; clj -m cljs.main --optimizations advanced -co '{:pseudo-names true}' -c example.core

(let [a (atom 0)]
  (swap! a inc)
  (js/console.log @a))

var $a_528$$ = new $cljs$core$Atom$$;
$cljs$core$swap_BANG_$$.$cljs$core$IFn$_invoke$arity$2$($a_528$$, function($x$jscomp$125$$) {
    return $x$jscomp$125$$ + 1
});
console.log($cljs$core$_deref$$($a_528$$));
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>ClojureScript</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/9291/why-does-an-atom-not-implemented-the-iswap-protocol</guid>
<pubDate>Wed, 06 May 2020 18:19:56 +0000</pubDate>
</item>
<item>
<title>What is an order of protocol methods lookup in protocol implementation for types having subclass relationship</title>
<link>https://ask.clojure.org/index.php/8691/protocol-protocol-implementation-subclass-relationship</link>
<description>&lt;p&gt;Hi!&lt;/p&gt;
&lt;p&gt;Here is a code from honeysql:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(extend-protocol ToSql
  #?(:clj clojure.lang.Keyword
     :cljs cljs.core/Keyword)
  (to-sql [x]
    (let [s (name x)]
      (case (.charAt s 0)
        \% (let [call-args (string/split (subs s 1) #&quot;\.&quot; 2)]
             (to-sql (apply call (map keyword call-args))))
        \? (to-sql (param (keyword (subs s 1))))
        (quote-identifier x))))

  .... ;SKIPPED

  #?(:clj Object :cljs default)
  (to-sql [x]
    #?(:clj (add-anon-param x)
       :cljs (if (sequential? x)
               (seq-&amp;gt;sql x)
               (add-anon-param x)))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Assume i'm calling&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(to-sql :column-name)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Method selected to be called depends on lookup &lt;em&gt;order&lt;/em&gt; because Keyword is a subclass of Object and :column-name IS-A Keyword &lt;em&gt;and&lt;/em&gt; IS-A Object.&lt;/p&gt;
&lt;p&gt;I didn't find any info about defined order of methods lookup in clojure protocol documentation.&lt;/p&gt;
&lt;p&gt;Also i investigated implementation of extend-protocol and as i understood there is a usual HashMap for :impls where all methods are stored so again there is no any guarantee about order of lookup.&lt;/p&gt;
&lt;p&gt;Another words, what are the rules of extending protocol for types which have subclass relations or maybe this is not correct at all and i should extend protocol only for types which don't have any type relations.&lt;/p&gt;
&lt;p&gt;Thanks!&lt;/p&gt;
</description>
<category>Protocols</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/8691/protocol-protocol-implementation-subclass-relationship</guid>
<pubDate>Mon, 07 Oct 2019 16:24:49 +0000</pubDate>
</item>
<item>
<title>regex equality</title>
<link>https://ask.clojure.org/index.php/8566/regex-equality</link>
<description>&lt;p&gt;How to check regexp equality in nested structures?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(= #&quot;.&quot; #&quot;.&quot;) ;; #=&amp;gt; false
(= [#&quot;.&quot;] [#&quot;.&quot;]) ;; #=&amp;gt; false
(= [&quot;.&quot;] [&quot;.&quot;]) ;; #=&amp;gt; true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I believe that a regexp is a value object.&lt;br&gt;
So two regexp are equal if they equals literally.&lt;/p&gt;
&lt;p&gt;Is it possible to update &lt;code&gt;=&lt;/code&gt; function for regexp equality support?&lt;/p&gt;
&lt;p&gt;Maybe like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defprotocol IEquals
 (equals [a b]))

(extend-protocol IEquals
  Object
  (equals [a b] (.equals a b))
  
  Pattern
  (equals [a b]
    (and
      (instance? Pattern b)
      (= (str a) (str b))) 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And &lt;code&gt;clojure.lang.Util.equiv&lt;/code&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Util.java#L33&quot;&gt;uses&lt;/a&gt;&lt;br&gt;
&lt;code&gt;IEquals#equals&lt;/code&gt; instead of &lt;code&gt;Object#equals&lt;/code&gt;.&lt;br&gt;
But I down know how to call protocol method from &lt;code&gt;clojure.lang.Util&lt;/code&gt;.&lt;/p&gt;
</description>
<category>Compiler</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/8566/regex-equality</guid>
<pubDate>Sat, 07 Sep 2019 14:03:23 +0000</pubDate>
</item>
<item>
<title>Protocol implementations via metadata: ClojureScript behaves differently from Clojure</title>
<link>https://ask.clojure.org/index.php/8497/protocol-implementations-metadata-clojurescript-differently</link>
<description>&lt;p&gt;If you extend a type to implement a protocol, and then create an instance of that type that carries its own implementation of the same protocol in its metadata, ClojureScript will still use the implementation from the type, whereas Clojure uses the more specific metadata implementation.&lt;/p&gt;
&lt;p&gt;Here's a brief example based on one of the tests for ClojureScript's protocol metadata implementation.&lt;/p&gt;
&lt;p&gt;Edit: I am unable to make the code sample presentable in this editor, please see this gist instead: &lt;a rel=&quot;nofollow&quot; href=&quot;https://gist.github.com/cjohansen/a24257ecb5db15c7e20aaa25ff713b30&quot;&gt;https://gist.github.com/cjohansen/a24257ecb5db15c7e20aaa25ff713b30&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(defprotocol ExtMetaProtocol&lt;br&gt;
  :extend-via-metadata true&lt;br&gt;
  (ext-meta-protocol [x]))&lt;/p&gt;
&lt;p&gt;(ext-meta-protocol (with-meta {} {`ext-meta-protocol (fn [_] 1)})) ;;=&amp;gt; 1&lt;/p&gt;
&lt;p&gt;(extend-type clojure.lang.PersistentArrayMap&lt;br&gt;
  ExtMetaProtocol&lt;br&gt;
  (ext-meta-protocol [m]&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;2))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(ext-meta-protocol {}) ;;=&amp;gt; 2&lt;br&gt;
(ext-meta-protocol (with-meta {} {`ext-meta-protocol (fn [_] 1)})) ;;=&amp;gt; cljs =&amp;gt; 2, clj =&amp;gt; 1&lt;/p&gt;
</description>
<category>ClojureScript</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/8497/protocol-implementations-metadata-clojurescript-differently</guid>
<pubDate>Sat, 31 Aug 2019 07:05:57 +0000</pubDate>
</item>
<item>
<title>Replacing core interfaces with protocols</title>
<link>https://ask.clojure.org/index.php/8323/replacing-core-interfaces-with-protocols</link>
<description>&lt;p&gt;Currently &lt;code&gt;IFn&lt;/code&gt;, &lt;code&gt;IDererf&lt;/code&gt; etc implemented as interfaces in clojure but these are protocols in clojurescript.&lt;br&gt;
Are there any plans to fix this mismatch?&lt;/p&gt;
</description>
<category>Compiler</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/8323/replacing-core-interfaces-with-protocols</guid>
<pubDate>Sun, 04 Aug 2019 16:04:40 +0000</pubDate>
</item>
</channel>
</rss>