<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Clojure Q&amp;A - Recent questions in Multimethods</title>
<link>https://ask.clojure.org/index.php/questions/clojure/multimethods</link>
<description></description>
<item>
<title>fn? and multimethods</title>
<link>https://ask.clojure.org/index.php/14169/fn-and-multimethods</link>
<description>&lt;p&gt;The docstring for &lt;code&gt;clojure.core/fn?&lt;/code&gt; says &quot;Returns true if x implements Fn, i.e. is an object created via fn.&quot;, defined in &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/clojure/commit/10541c0254973ce045305499d4b5622073ede622&quot;&gt;this commit from 2008&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Multimethods semantically act as functions. They're not collections (maps), they're not pieces of data that work like functions for ease (keywords), they're procedures with behavior and input and output. Protocol methods semantically act like functions as well. However, multimethods don't respond to &lt;code&gt;fn?&lt;/code&gt; because they don't implement &lt;code&gt;clojure.lang.Fn&lt;/code&gt;, they implement &lt;code&gt;clojure.lang.AFn&lt;/code&gt;, whereas protocol methods do respond to &lt;code&gt;fn?&lt;/code&gt; because they are created with &lt;code&gt;fn*&lt;/code&gt; in the &lt;code&gt;defprotocol&lt;/code&gt; macro.&lt;/p&gt;
&lt;p&gt;This has led to confusion in my code where I have a sequence of function-like objects and in certain cases I want to select only the &quot;semantically function&quot; objects. It has forced me to write &lt;code&gt;fn+?&lt;/code&gt; which is implemented as &lt;code&gt;(or (fn? x) (instance? clojure.lang.MultiFn x))&lt;/code&gt;. Now, having written it, it works fine and my immediate problem is solved. However, I think this points to an underlying semantic mismatch between multimethods and their implementation.&lt;/p&gt;
&lt;p&gt;It would benefit me and &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/marick/suchwow/blob/111cd4aa21ee23552742701bfe52e593b65fb0f8/src/such/types.clj#L30-L33&quot;&gt;others&lt;/a&gt; to have this mismatch cleaned up.&lt;/p&gt;
</description>
<category>Multimethods</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14169/fn-and-multimethods</guid>
<pubDate>Mon, 07 Oct 2024 21:25:33 +0000</pubDate>
</item>
<item>
<title>Memory leak using the default method of a multimethod</title>
<link>https://ask.clojure.org/index.php/10532/memory-leak-using-the-default-method-of-a-multimethod</link>
<description>&lt;p&gt;An easy way to reproduce:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Clojure 1.10.2
user=&amp;gt; (defmulti f identity)
#'user/f
user=&amp;gt; (defmethod f :default [x] nil)
#object[clojure.lang.MultiFn 0x4bb8855f &quot;clojure.lang.MultiFn@4bb8855f&quot;]
user=&amp;gt; (dotimes [_ 100000] (f (byte-array 1000000)))

Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread &quot;main&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you adjust the numbers in such a way so that there's no OOM error, you'll see a persistent leak.&lt;/p&gt;
&lt;p&gt;The culprit seems to be &lt;code&gt;MultiFn.findAndCacheBestMethod&lt;/code&gt; caching every single value that was matched with the default method.&lt;/p&gt;
</description>
<category>Multimethods</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/10532/memory-leak-using-the-default-method-of-a-multimethod</guid>
<pubDate>Wed, 28 Apr 2021 08:02:47 +0000</pubDate>
</item>
<item>
<title>Self-Like Pattern Using Multi-Methods</title>
<link>https://ask.clojure.org/index.php/10449/self-like-pattern-using-multi-methods</link>
<description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;I’ve reading about the Self language, and got experimenting with multi-methods to mimick Self-style messages. I was curious what folks think about this pattern:&lt;/p&gt;
&lt;p&gt;(ns self)&lt;/p&gt;
&lt;p&gt;(def path &quot;./hello.txt&quot;)&lt;/p&gt;
&lt;p&gt;(defn inst [msg]&lt;br&gt;
  (if (map? msg) (keys msg) msg)&lt;br&gt;
)&lt;/p&gt;
&lt;p&gt;(defmulti hello inst)&lt;/p&gt;
&lt;p&gt;(defmethod hello [:save] [msg]&lt;br&gt;
  (spit path (msg :save))&lt;br&gt;
)&lt;/p&gt;
&lt;p&gt;(defmethod hello :load [msg]&lt;br&gt;
  (slurp path)&lt;br&gt;
)&lt;/p&gt;
&lt;p&gt;(defn do-run [h]&lt;br&gt;
  (h {:save &quot;world&quot;})                                                            &lt;br&gt;
  (println (h :load)) &lt;br&gt;
)&lt;/p&gt;
&lt;p&gt;(defn run [opts]&lt;br&gt;
  (do-run hello)&lt;br&gt;
)&lt;/p&gt;
&lt;p&gt;Do you find this pattern interesting, useful? The example doesn’t show it, but there could be messages with multiple keywords.&lt;/p&gt;
&lt;p&gt;Thanks,&lt;br&gt;
- Quenio&lt;/p&gt;
</description>
<category>Multimethods</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/10449/self-like-pattern-using-multi-methods</guid>
<pubDate>Sat, 10 Apr 2021 02:25:08 +0000</pubDate>
</item>
<item>
<title>Please add dispatch-fn to clojure.core</title>
<link>https://ask.clojure.org/index.php/10261/please-add-dispatch-fn-to-clojure-core</link>
<description>&lt;p&gt;CLJS has:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cljs.user=&amp;gt; (source dispatch-fn)
(defn dispatch-fn
  &quot;Given a multimethod, return it's dispatch-fn.&quot;
  [multifn] (-dispatch-fn multifn))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Can we have this core fn on the JVM as well?&lt;/p&gt;
</description>
<category>Multimethods</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/10261/please-add-dispatch-fn-to-clojure-core</guid>
<pubDate>Sat, 27 Feb 2021 13:49:52 +0000</pubDate>
</item>
<item>
<title>Best way to test for an integer (including java.lang.Integer) in a multimethod dispatch?</title>
<link>https://ask.clojure.org/index.php/9978/best-test-integer-including-integer-multimethod-dispatch</link>
<description>&lt;p&gt;It seems (?) like Clojure makes all integers instances of java.lang.Long. I recently found a library I use (which wraps a Java lib) was returning java.lang.Integer instead. This broke a multimethod I have which was dispatching on class.&lt;/p&gt;
&lt;p&gt;My solution was to simply make a new defmethod to handle java.lang.Integer. It's exactly like the defmethod for handling java.lang.Long.&lt;/p&gt;
&lt;p&gt;Is there a more elegant way to do this? Can a defmethod be made to handle a set of dispatch values? There is a common ancestor class for Integer and Long, java.lang.Number, but I don't want to use that because it will catch floats, which should fall through.&lt;/p&gt;
&lt;p&gt;I suppose I could rewrite the dispatch to test if the class of input is Integer or Long and just dispatch those as :int and then dispatch java.lang.String as :string, although that actually may end up being more code :)&lt;/p&gt;
&lt;p&gt;Current form is along these lines:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; (defmulti int-or-nil class)

(defmethod int-or-nil java.lang.Long
  [integer]
  (identity integer))

(defmethod int-or-nil java.lang.Integer
  [integer]
  (identity integer))

(defmethod int-or-nil java.lang.String
  [maybe-int-string]
  (try (Integer/parseInt maybe-int-string)
       (catch java.lang.NumberFormatException e)))

(defmethod int-or-nil :default
  [not-int])
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Multimethods</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/9978/best-test-integer-including-integer-multimethod-dispatch</guid>
<pubDate>Mon, 28 Dec 2020 01:20:38 +0000</pubDate>
</item>
<item>
<title>Multimethods resolutions when they have the same dispatch value</title>
<link>https://ask.clojure.org/index.php/9910/multimethods-resolutions-when-they-have-same-dispatch-value</link>
<description>&lt;p&gt;When two multimethods have the same dispatch value, what is the method of resolution?&lt;/p&gt;
&lt;p&gt;In order to answer this questions, I experimented by creating four files (core.cljs, a.clj, b.clj, interface.clj [where  `defmulti` is defined]), implemented some methods in a and b namespace with the same dispatch value. &lt;/p&gt;
&lt;p&gt;Finally in &lt;code&gt;core&lt;/code&gt; namespace, I required &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt;, and observed the resolution was given by the order of the import of the namespace.&lt;/p&gt;
&lt;p&gt;However, in a bigger project, the order did not have an impact: I was overriding a multimethod in a library, and I suspect the resolution was made with respect to the folder in the classpath.&lt;/p&gt;
&lt;p&gt;Can anyone confirm or infirm my hypothesis?&lt;/p&gt;
&lt;p&gt;Best regards,&lt;br&gt;
David&lt;/p&gt;
</description>
<category>Multimethods</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/9910/multimethods-resolutions-when-they-have-same-dispatch-value</guid>
<pubDate>Wed, 02 Dec 2020 10:08:44 +0000</pubDate>
</item>
<item>
<title>Implementing a type or record to support defmethod in CLJ</title>
<link>https://ask.clojure.org/index.php/9045/implementing-a-type-or-record-to-support-defmethod-in-clj</link>
<description>&lt;p&gt;Thanks to &lt;code&gt;IMultiFn&lt;/code&gt; in CLJS types and records can be easily extended to behave as multimethods. For example:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;`&lt;/code&gt;(defrecord MyMulti&lt;br&gt;
  [add-method remove-method dispatch-fn method-table]&lt;br&gt;
  IMultiFn&lt;br&gt;
  (-add-method [_ dispatch-val f]&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(add-method dispatch-val f))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  (-remove-method [_ dispatch-val]&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(remove-method dispatch-val))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;  (-methods [_] @method-table))&lt;/p&gt;
&lt;p&gt;(def my-multi (-&amp;gt;MyMulti ...))&lt;/p&gt;
&lt;p&gt;(defmethod my-multi :foo&lt;br&gt;
  [x]&lt;br&gt;
  ...)&lt;br&gt;
&lt;code&gt;`&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In Clojure however this isn't as easy because multimethods are not implemented using protocols. IS there ANY way to make a record or type to work with defmethod in CLJ?&lt;/p&gt;
&lt;p&gt;Thanks!&lt;/p&gt;
</description>
<category>Multimethods</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/9045/implementing-a-type-or-record-to-support-defmethod-in-clj</guid>
<pubDate>Fri, 17 Jan 2020 18:37:33 +0000</pubDate>
</item>
<item>
<title>behavior of deftests after adding assert-expr methods</title>
<link>https://ask.clojure.org/index.php/8651/behavior-of-deftests-after-adding-assert-expr-methods</link>
<description>&lt;p&gt;The following behavior surprised me&lt;br&gt;
1. define a test that calls &lt;code&gt;(is (=&lt;/code&gt; on one item&lt;br&gt;
2. override the multimethod &lt;code&gt;clojure.test/assert-expr&lt;/code&gt; to define custom testing for &lt;code&gt;=&lt;/code&gt; such that it should error if only one item is present&lt;br&gt;
3. run your test and the multimethod is not invoked since it does not error&lt;br&gt;
4. redefine the test&lt;br&gt;
5. the new multimethod is now invoked.&lt;/p&gt;
&lt;p&gt;I'm sure there's a smaller repro but this is the real world use case that came up. CIDER changes this reporting in its middleware but the middleware is dynamically loaded after startup only when needed. Thus this behavior only occurs after using CIDER's testing features and &lt;em&gt;if you redefine your tests&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I'm wondering if this is behaving as expected since deftest stuffs the test in meta or if this is an actual bug.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(require '[clojure.test :refer [deftest is assert-expr]])
(deftest foo (is (= (println 1))))

(foo) ;; no error

(defn =-body
  [msg expected more]
  (if (seq more)
    `(let [more# (list ~@more)
           expected# ~expected
           result# (apply = expected# more#)]
       (-&amp;gt;&amp;gt; (if result#
              {:type :pass}
              {:type :fail
               :diffs (-&amp;gt;&amp;gt; (remove #(= expected# %) more#)
                           (map #(vector % (data/diff expected# %))))})
            (merge {:message ~msg
                    :expected expected#
                    :actual more#})
            test/do-report)
       result#)
    `(throw (Exception. &quot;= expects more than one argument&quot;))))

(defmethod assert-expr '= [msg [_ expected &amp;amp; more]]
  (=-body msg expected more))

(foo) ;; no error
(deftest foo (is (= (println 1))))
(foo) ;; error
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Multimethods</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/8651/behavior-of-deftests-after-adding-assert-expr-methods</guid>
<pubDate>Mon, 23 Sep 2019 22:32:29 +0000</pubDate>
</item>
<item>
<title>Supporting `add-method` on multi fns to install a function instead of a function tail</title>
<link>https://ask.clojure.org/index.php/724/supporting-method-multi-install-function-instead-function</link>
<description>&lt;p&gt;Whenever methods on a multifn need to be installed within a closure (usually to support lifecycle management) using defmethod can be a bit cumbersome and forces having all&lt;br&gt;
method bodies within the closure.&lt;/p&gt;
&lt;p&gt;Two cases strike me as most relevant:&lt;/p&gt;
&lt;p&gt;If you need a method to capture bindings, it would involve creating a bound-fn and calling that from the defmethod.&lt;/p&gt;
&lt;p&gt;With dependency injection framework, you most likely method installation when dependencies are available, making calling defmethod cumbersome.&lt;/p&gt;
&lt;p&gt;I attached an example in foo.clj to try to make things clearer and a naive patch.&lt;/p&gt;
&lt;p&gt;After discussing things on #clojure-dev with @alexmiller, it seems it would be feasible to add an &lt;code&gt;add-method&lt;/code&gt; function and to have &lt;code&gt;defmethod&lt;/code&gt; use that.&lt;/p&gt;
</description>
<category>Multimethods</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/724/supporting-method-multi-install-function-instead-function</guid>
<pubDate>Fri, 24 May 2019 05:02:31 +0000</pubDate>
</item>
<item>
<title>MultiFn.prefers() ignores the multimethod's internal hierarchy</title>
<link>https://ask.clojure.org/index.php/3332/multifn-prefers-ignores-multimethods-internal-hierarchy</link>
<description>See &lt;a href=&quot;https://groups.google.com/forum/#!topic/clojure/3nMn6TiBGOg,&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;https://groups.google.com/forum/#!topic/clojure/3nMn6TiBGOg,&lt;/a&gt; which hasn't had any response.&lt;br /&gt;
&lt;br /&gt;
prefers(x,y) visits ancestors by calling parents.invoke() recursively.&lt;br /&gt;
This visits the parents in the global hierarchy, not the multimethod's hierarchy. &lt;br /&gt;
Is this the intended behavior? Why would that be?&lt;br /&gt;
&lt;br /&gt;
On the assumption that prefer-method should behave the same for a local vs the global-hierarchy, below are 2 unit tests. &lt;br /&gt;
MultiFn-prefers-with-local-hierarchy fails with a &amp;quot;Multiple methods&amp;quot; IllegalArgumentException.&lt;br /&gt;
MultiFn-prefers-with-global-hierarchy succeeds.&lt;br /&gt;
&lt;br /&gt;
(test/deftest MultiFn-prefers-with-local-hierarchy&lt;br /&gt;
&amp;nbsp;&amp;nbsp;(def local-hierarchy &lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(let [h (make-hierarchy)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h (derive h ::c0 ::b0)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h (derive h ::d0 ::c0)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h (derive h ::d0 ::a0)]&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;h))&lt;br /&gt;
&amp;nbsp;&amp;nbsp;(defmulti local identity :hierarchy #'local-hierarchy)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;(defmethod local ::a0 [x] [::a0 x]) &lt;br /&gt;
&amp;nbsp;&amp;nbsp;(defmethod local ::c0 [x] [::c0 x]) &lt;br /&gt;
&amp;nbsp;&amp;nbsp;(prefer-method local ::b0 ::a0)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;(test/is (= [::c0 ::d0] (local ::d0)))))&lt;br /&gt;
&lt;br /&gt;
(test/deftest MultiFn-prefers-with-global-hierarchy&lt;br /&gt;
&amp;nbsp;&amp;nbsp;(derive ::c1 ::b1)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;(derive ::d1 ::c1)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;(derive ::d1 ::a1)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;(defmulti global identity)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;(defmethod global ::a1 [x] [::a1 x]) &lt;br /&gt;
&amp;nbsp;&amp;nbsp;(defmethod global ::c1 [x] [::c1 x]) &lt;br /&gt;
&amp;nbsp;&amp;nbsp;(prefer-method global ::b1 ::a1)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;(test/is (= [::c1 ::d1] (global ::d1))))&lt;br /&gt;
&lt;br /&gt;
If this is in fact wrong, the fix is pretty easy. I'll submit a patch once it's confirmed this is a real problem.</description>
<category>Multimethods</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/3332/multifn-prefers-ignores-multimethods-internal-hierarchy</guid>
<pubDate>Sat, 09 Sep 2017 21:26:13 +0000</pubDate>
</item>
</channel>
</rss>