在实现Clojure协议时,重载方法能否调用其重载的对应方?
以下是重载协议定义的一部分:在实现Clojure协议时,重载方法能否调用其重载的对应方?,clojure,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] Cl
(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中使用第一个函数编译了这两个定义,然后返回并添加了第二个
但是,当我将协议定义移动到一个单独的文件中并试图重新编译整个过程时,当第二个方法尝试调用第一个方法时,它会抛出一个错误,可能是因为第一个方法尚未定义
Clojurereify
文档有以下注释:
如果在协议/接口中重载了一个方法,则
必须提供独立的方法定义
我想这些不是独立的定义
正确的方法是什么?下面是一个在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
这里是一个相互递归的示例(无基本情况)
你在这里做的很好 考虑这个例子:
(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}
;=>(创建边缘(SampleClient.)1 2 3)
{:操作:创建边,:this#,
:outV 1,:label 2,:inV 3,:data{}
; => (创建边缘(SampleClient.)1 2 3 4)
{:操作:创建边,:this#,
:outV 1,:label 2,:inV 3,:data 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]]))
在我的示例中,您在哪里看到了相互递归?当您导入协议定义时,似乎出现了问题——您必须提供名称空间来执行其调用。@espeed-是的,您是正确的,如果协议是在不同的线程中定义的——因为协议中有很多函数,并且从协议定义文件到客户端实现有一对一的映射,所以我只删除了
:仅位,现在使用(:use[bulls.base.client])
。我最初的困惑是没有意识到协议是如何工作的——没有意识到协议是名称空间定义的来源,而不是实现。
(ns bulbs.neo4jserver.client
(:use [bulbs.base.client :only [create-edge ClientProtocol]]))