3

Other is a more complex version (wrapping) of What. It does what What does but much more. I took care to define 2 namespaces.

(ns what)

(defprotocol IWhatever
  (whatever [this]))

(deftype What []
  IWhatever
  (whatever [this]
            (str "whatever")))

(whatever (->What))

(ns other (:require what))

(deftype Other []
  what/IWhatever
  (whatever [this]
            (what/whatever (what/->What))))

(whatever (->Other)) ;bad line

The error is:

clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: Unable to resolve symbol: whatever in this context, compiling:(C:\...)

Why won't this last expression resolve? It's like the name can't be found, but as you can see I redefined it under the current namespace.

It's nonsense code but I used the simplest example of the problem to illustrate the point. I'm running this in LightTable if that's relevant.

Mario
  • 6,572
  • 3
  • 42
  • 74
  • 2
    When calling the protocol function, you need to use a qualified symbol, i.e. `(dict/get man :name)` instead of `(get man :name)`. – Alex Sep 30 '14 at 18:19
  • It won't call the Dictionary version, since the version in Dictionary doesn't have implementation. Try it in repl and see for yourself. – soulcheck Sep 30 '14 at 19:03
  • 2
    @Mario I think you're missing the point of protocols. A protocol defines a set of polymorphic functions. You call a protocol function, and it dispatches based on the type of the first argument. If you had to call a different function for each implementing type, it would defeat the whole purpose. – Alex Sep 30 '14 at 19:10
  • What happens in the REPL when you call `dict/get` on an `Item`? Have you tried that yet? – Alex Sep 30 '14 at 19:14
  • I moved all the code to one file and reduced it to it's simplest form to better illustrate the point. – Mario Sep 30 '14 at 20:00
  • Again: have you tried my original suggestion of using a namespace-qualified call to `what/whatever` from your `other` namespace? – Alex Sep 30 '14 at 20:39
  • 3
    The call won't resolve because `extend-type` doesn't define new functions in the current namespace. It adds functions to the dispatch table of the protocol being extended. – Alex Sep 30 '14 at 20:40
  • @Mario it doesn't resolve cause **you have to qualify** the function from the protocol if the protocol is in another namespace. **try** `(what/whatever oth)` and convince yourself. – soulcheck Sep 30 '14 at 23:39
  • It worked for me without problems. You sure you didn't redefine things somewhere along the way? – soulcheck Sep 30 '14 at 23:42
  • @Mario I just copied and pasted your code into light table. As is it gives the error you mention. Adding the what/ that soulcheck suggests works for me. You might want to try it again with a clean environment. – stonemetal Sep 30 '14 at 23:59
  • The code in the screenshot you posted is different from your sample above. There, `(what/wht)` is attempting to call an object of type `What` as a function, and it's not a function. That exception (a) is different than the exception posted above, and (b) happens to be thrown from inside the function that you claim not to be able to call. – Alex Oct 01 '14 at 00:31
  • I finally got it. Thanks for all your time. SO appreciative. – Mario Oct 01 '14 at 02:42
  • @Mario, instead of editing the question with the answer, could you post the answer below and accept it? That's a perfectly valid thing to do here. :-) – Jeremy Oct 01 '14 at 20:19

1 Answers1

3

Qualify the final line with the namespace of where the protocol was defined. I kept thinking to try to call the whatever method in the other namespace since it was defined there.

(what/whatever (->Other))

Thanks goes to @soulcheck and everyone else who took time to help.

Mario
  • 6,572
  • 3
  • 42
  • 74