3

首次尝试在 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!!!
4

1 回答 1

4

看起来你回答了你自己的问题,但万一有人在这里结束......

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

于 2013-03-27T11:14:00.883 回答