When implementing the Clojure protocol, can an overloaded method call an overloaded instance?

Here is part of the definition of an overloaded protocol:

(defprotocol ClientProtocol
  (create-edge
    [this outV label inV] 
    [this outV label inV data])

And here is part of its implementation:

(ns bulbs.neo4jserver.client
  (:use [bulbs.base.client :only [ClientProtocol]]))

(deftype Neo4jClient [ns config]
  ClientProtocol

  (create-edge
    [this outV label inV data]
    (let [inV-uri (utils/normalize-uri (build-path neo4j-uri vertex-path inV))
          path (build-path vertex-path, outV, "relationships")
          params {:to inV-uri, :type label, :data (first data)}]
      (post config path params)))

  (create-edge
    [this outV label inV]
    ;; it doesn't like this call...
    (create-edge this outV label inV nil)) 

It throws this error when the second method tries to call the first:

java.lang.RuntimeException: Unable to resolve symbol: create-edge in this context

I had both definitions working earlier in SLIME when I compiled it with the first function, and then came back and added the second.

But when I moved the protocol definition to a separate file and tried to recompile all of this, it throws an error when the second method tries to call the first, apparently because the first method has not yet been defined.

Clojure docs reifyhave the following comment:

If the method is overloaded in the protocol / interface, several independent method definitions should be provided.

http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/reify

, .

?

+3
3

.

(ns bulbs.neo4jserver.client
  (:use [bulbs.base.client :only [ClientProtocol]]))

Clojure . :only.

(ns bulbs.neo4jserver.client
  (:use [bulbs.base.client :only [create-edge ClientProtocol]]))
+4

, clojure 1.4.0

(ns hello.core)
(defprotocol ClientProtocol
 (create-edge
    [this outV label inV] 
    [this outV label inV data]))

(deftype Neo4jClient []
  ClientProtocol

 (create-edge
   [this outV label inV data]
    4)

  (create-edge
    [this outV label inV]
    (create-edge this outV label inV nil)))

hello.core> (create-edge (Neo4jClient.) 2 3 4)
4

hello.core> (create-edge (Neo4jClient.) 2 3 4 5)
4

( )

(deftype Neo4jClient []
  ClientProtocol

  (create-edge
    [this outV label inV data]
    (println "OMG im in a looooooop...")
    (create-edge this 1 2 3))

  (create-edge
    [this outV label inV]
    (println "AHHH im in a looooooop...")
    (create-edge this 1 2 3 4)))


hello.core> (create-edge (Neo4jClient.) 1 2 3 4)
OMG im in a looooooop...
AHHH im in a looooooop...
OMG im in a looooooop...
AHHH im in a looooooop...
OMG im in a looooooop...
AHHH im in a looooooop...
OMG im in a looooooop...
AHHH im in a looooooop...
+2

What you do here works great.

Consider the following example:

(defprotocol ClientProtocol
  (create-edge
    [this outV label inV]
    [this outV label inV data]))

(deftype SampleClient []
  ClientProtocol

  (create-edge
    [this outV label inV]
      (create-edge this outV label inV {}))

  (create-edge
    [this outV label inV data]
      {:action :create-edge :this this :outV outV :label label :inV inV :data data}))

Startup behavior as expected:

; => (create-edge (SampleClient.) 1 2 3)
{:action :create-edge, :this #<SampleClient user.SampleClient@63a2cc03>,
 :outV 1, :label 2, :inV 3, :data {}}
; => (create-edge (SampleClient.) 1 2 3 4)
{:action :create-edge, :this #<SampleClient user.SampleClient@7144c1a4>,
 :outV 1, :label 2, :inV 3, :data 4}
0
source

All Articles