在实现Clojure协议时,重载方法可以调用其重载的对应方吗?

时间:2012-05-18 00:15:36

标签: clojure

以下是重载协议定义的一部分:

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

以下是其实施的一部分:

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

当第二种方法试图调用第一种方法时,它会发出此错误:

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

当我使用第一个函数编译它时,我在SLIME中使用了两个定义,然后返回并添加了第二个。

但是当我将协议定义移动到一个单独的文件并尝试重新编译整个文件时,当第二个方法尝试调用第一个方法时,它会抛出错误,大概是因为第一个方法尚未定义。

Clojure reify文档有这样的评论:

  

如果方法在协议/接口中过载,则为多个   必须提供独立的方法定义。

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

我认为这些不是独立的定义。

采用这种方式的正确方法是什么?

3 个答案:

答案 0 :(得分: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]]))

答案 1 :(得分:2)

这是一个适用于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 :(得分: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 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}