2013-08-30 20 views
2

之间的协议,我有一个交叉的命名空间的协议:如何共享的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代码,所以我需要将其分解为一个函数。这会是一个更好的方式来解决这个问题吗?

谢谢!

回答

6

secondsxxx.shared.interfaces定义,所以这是你所需要的:require/:use才能够称之为:

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

;; (seconds ...) will now work 

要精心,一个defprotocol表达式创建无功控股协议,底层JVM接口在JVM端(在ClojureScript端没有对应的)和每个协议方法的Var。协议方法可以通过这些Vars调用,就像其他Clojure函数一样。

当您为记录/类型实现协议时,与您在xxx.time命名空间中执行的操作一样,如果您实际上未调用方法,则甚至不需要拉入这些Vars(提供实现的单独问题)。同样,需要调用协议方法的名称空间,但并不太在意它调用的对象的特定类型,只需要拉入协议定义的名称空间并使用相关的Vars,而不需要:require任何实施的名称空间。

+2

至于代码共享的问题,我认为可以共享任何作为共享代码的东西并分析协议方法的平台特定实现当然是使更多代码可共享的有效方法。是否值得这可能取决于实际避免多少重复。无论如何,如上所述,原始问题与共享无关。 –