2012-05-18 30 views
3

這裏有一個重載的協議定義的一部分:在實現Clojure協議時,重載的方法是否可以調用它的過載對象?

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

下面是其實現的一部分:

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

(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)) 

當第二種方法試圖調用第一它噴涌這個錯誤

當我用第一個函數對它進行編譯,然後返回並添加了第二個函數時,我在SLIME中的兩個定義都工作得更早。

但是當我將協議定義移動到一個單獨的文件並試圖重新編譯整個事情時,它會拋出一個錯誤,當第二個方法試圖調用第一個,大概是因爲第一個方法尚未定義。

Clojure的reify文檔有此評論:

如果一個方法是在協議/接口過載,多個獨立 方法定義必須提供。

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

我想這些都不是獨立定義。

什麼是正確的方法來解決這個問題?

回答

4

你的命名空間聲明是錯誤的。

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

協議函數是正常的Clojure函數,必須這樣處理。所以你必須將它們包含在你的:only條款中。

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

中,那麼是正確的 - 謝謝 - 由於協議中有許多功能和從協議定義文件到客戶端實現的一對一映射,我只是放棄':only'位,現在使用'(:use [bulbs.base.client])'。我最初的困惑是沒有意識到協議是如何工作的 - 沒有意識到協議是命名空間定義來自何處,而不是實現。 – espeed

2

這裏是一個stipped下來的例子,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... 
+0

在我的例子中,你在哪看到相互遞歸?它看起來像是在導入協議定義時發生的問題 - 您必須提供命名空間才能執行其調用。 – espeed

+0

哎呀,那部分來自我的剪切和粘貼錯誤。 –

+0

@espeed - 是的,如果協議定義在不同的 – Ankur

0

你是什麼在這裏做的很好。

考慮這個例子:

(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})) 

行爲在運行時作爲預期:

; => (create-edge (SampleClient.) 1 2 3) 
{:action :create-edge, :this #<SampleClient [email protected]>, 
:outV 1, :label 2, :inV 3, :data {}} 
; => (create-edge (SampleClient.) 1 2 3 4) 
{:action :create-edge, :this #<SampleClient [email protected]>, 
:outV 1, :label 2, :inV 3, :data 4} 
相關問題