Welcome! Please see the About page for a little more info on how this works.

+2 votes
in Multimethods by
closed by
See https://groups.google.com/forum/#!topic/clojure/3nMn6TiBGOg, which hasn't had any response.

prefers(x,y) visits ancestors by calling parents.invoke() recursively.
This visits the parents in the global hierarchy, not the multimethod's hierarchy.
Is this the intended behavior? Why would that be?

On the assumption that prefer-method should behave the same for a local vs the global-hierarchy, below are 2 unit tests.
MultiFn-prefers-with-local-hierarchy fails with a "Multiple methods" IllegalArgumentException.
MultiFn-prefers-with-global-hierarchy succeeds.

(test/deftest MultiFn-prefers-with-local-hierarchy
  (def local-hierarchy
    (let [h (make-hierarchy)
          h (derive h ::c0 ::b0)
          h (derive h ::d0 ::c0)
          h (derive h ::d0 ::a0)]
  (defmulti local identity :hierarchy #'local-hierarchy)
  (defmethod local ::a0 [x] [::a0 x])
  (defmethod local ::c0 [x] [::c0 x])
  (prefer-method local ::b0 ::a0)
  (test/is (= [::c0 ::d0] (local ::d0)))))

(test/deftest MultiFn-prefers-with-global-hierarchy
  (derive ::c1 ::b1)
  (derive ::d1 ::c1)
  (derive ::d1 ::a1)
  (defmulti global identity)
  (defmethod global ::a1 [x] [::a1 x])
  (defmethod global ::c1 [x] [::c1 x])
  (prefer-method global ::b1 ::a1)
  (test/is (= [::c1 ::d1] (global ::d1))))

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.
closed with the note: Released in 1.11.0-alpha4

3 Answers

0 votes

Comment made by: alexmiller

Patch welcome

Hi Alex,

I submitted a patch for this a couple years ago at https://clojure.atlassian.net/browse/CLJ-2234, is there anything else I need to do to get it considered? Happy to make any changes you want.
We consider priority based (partially) on the number of votes here, so this is pretty far down the list atm.
0 votes

Comment made by: palisades-lakes

I'm not sure about the change to preferMethod.
I've moved resetCache to the beginning so that
perfers() can be called with the current state of the hierarchy. Since we are in a write lock, I don't think it's necessary to call it again.

0 votes
Reference: https://clojure.atlassian.net/browse/CLJ-2234 (reported by palisades-lakes)