Clojurescript协议用法?

时间:2012-07-10 20:56:01

标签: clojurescript

首先尝试使用ClojureScript中的协议。以下是协议定义/实现:

(defprotocol IDataTable
  (-pages [this])
  (-cnt! [this cnt])
  (-paginate [this])
 )

(deftype DataTable [id url info]
 IDataTable
 (-cnt! [_ cnt] (swap! info (fn [v] (assoc v :cnt cnt))) )
 (-pages [_]
   (inc (.round js/Math (/ (:cnt @info) (:length @info))))
 )

(-paginate [_]
  (let [arr (take 5 (drop (- (:page @info) 1) (range 1 (pages))))]
   (c/paging id (flatten ["Prev" arr "Next"]) )
  ))
 )

我对如何调用协议中定义的函数感到困惑。

以下是实例化的代码:

(def table-id "some-table")
(def paging (atom {:page 1 :length 10 :cnt 0  }))
(def data-table (DataTable. table-id "/list/data" paging))

以上代码有效,可以使用以下格式访问属性:

(js/alert (.-id data-table))

我面临的问题是如何调用协议中定义的函数。以下表单导致错误(运行时)。

 (-cnt! data-table 10) ;; Error: -cnt! is not a method
 (.-cnt! data-table 10) ;; Error

浏览生成的Javascript代码,它为函数提供了冗长的名称。

由于

编辑:想想我找到了答案。看起来我需要命名空间中的支持功能。

(defn cnt! [t cnt]
   (when (satisfies? IDataTable t)
     (-cnt! t cnt))
 )

使用上面定义的功能,我可以访问这些功能。不知道这是否是正确的方法?

EDIT2:嗯,通过进一步分析生成的javascript代码实现了一个不需要辅助函数的上述编辑,函数调用需要以命名空间为前缀:

 (:require [table :as tbl])

(def table-id "some-table")
(def paging (atom {:page 1 :length 10 :cnt 0  }))
(def data-table (DataTable. table-id "/list/data" paging))

 (tbl/-cnt! data-table 10) ;; Works!!!

1 个答案:

答案 0 :(得分:4)

看起来你回答了自己的问题,但万一有人到此为止......

协议方法会自动提升到声明它们的命名空间,这意味着如果要调用那些调用它们的函数,就好像它们是命名空间中的常规函数​​一样。