如何在Clojure和Clojure之间共享协议ClojureScript

时间:2013-08-30 06:33:42

标签: clojure clojurescript

我在交叉命名空间中有一个协议:

(ns xxx.shared.interfaces)

(defprotocol ITimer
  (seconds [timer] "Return time in seconds since timer began"))

我有Clojure的实现:

(ns xxx.time
  (:require [xxx.shared.interfaces :refer [ITimer]]))

(defrecord Timer [start-nanos]
  ITimer
  (seconds [timer] (double (/ (- (System/nanoTime) (:start-nanos timer))
                              1000000000))))

问题在于,当我在某些Clojure代码中使用此代码时,要求xxx.time命名空间与:refer :all一起抱怨它无法找到seconds

Unable to resolve symbol: seconds in this context

首先,是否可以通过这种方式共享协议?

其次,任何想法如何使这项工作?

第三,这实际上是一种很好的方式来进行这种代码共享吗?理想情况下我也想分享记录,但它依赖于Java代码,所以我需要将其分解为一个函数。这会是一个更好的方法吗?

谢谢!

1 个答案:

答案 0 :(得分:6)

{p> secondsxxx.shared.interfaces中定义,因此您需要:require / :use才能调用它:

(ns foo
  (:require [xxx.shared.interfaces :refer [seconds]]))

;; (seconds ...) will now work

详细说明,defprotocol表达式创建一个包含协议的Var,一个JVM端的底层JVM接口(在ClojureScript端没有这个接口)和每个协议方法的Var。然后可以通过这些Vars调用协议方法,就像任何其他Clojure函数一样。

当您为xxx.time命名空间实现记录/类型的协议时,如果您实际上没有调用方法,则甚至不需要引入这些Vars(另一个问题)从提供实施)。类似地,需要调用协议方法但不太关心它调用它们的特定类型对象的命名空间只需要引入协议定义命名空间并使用相关的Vars而不需要:require任何实现名称空间。