Clojure库:类/实例/纯功能

时间:2016-02-19 16:27:05

标签: clojure clojurescript

我正在开发一个clojure库,这在某种程度上需要是有状态的。为了不在抽象描述中花费太多单词,这里将是一个OOP示例,说明我如何能够使用库的API。

mylib = new lib();

state1 = mylib.getState();
mylib.continue();
state2 = mylib.getState();
mylib.continue();
state3 = mylib.getState();
[..]

(显然state1!= state2!= state3)

好的,怎么能用像Clojure这样的函数式语言来完成?

我想到了一种方法:

(require '(lib.core :as mylib))

(def state1 (mylib/start-state))
(def state2 (mylib/continue state1))
(def state3 (mylib/continue state2))
[..]

这种方法不会将状态保持分配给库端。我遇到的问题如下:我的状态确实保留了应该公开给API用户的信息。但它也保留了对下一个州的产生很重要的信息,但这与公众无关。

好吧,可能还有另一个函数(mylib/extract-relevant-data state1),它可以在oder中对状态进行后处理,以便"清洁使用"。

我真的很想学习在Clojure中我可以采用哪种方式来学习。

1 个答案:

答案 0 :(得分:2)

方法1:重新实施OOP 。我将last-time-called视为私人数据,将relevant state视为您要向人们展示的内容。

(defn start-state []
  (let [last-time-called (atom (new java.util.Date))
        relevant-state (atom 1)
        private-update (fn [] (swap! last-time-called (fn [_] (new java.util.Date))))
        get-state (fn [] (do (private-update)
                             @relevant-state))
        continue (fn [] (do (private-update)
                            (swap! relevant-state inc)
                            nil))]
    {:get-state get-state :continue continue}))

演示:

stack-prj.hiddenState> (def mylib (start-state))
#'stack-prj.hiddenState/mylib
stack-prj.hiddenState> ((mylib :get-state))
1
stack-prj.hiddenState> ((mylib :continue))
nil
stack-prj.hiddenState> ((mylib :get-state))
2
stack-prj.hiddenState> ((mylib :continue))
nil

请注意get-statecontinue可以last-time-called访问{。}}。

方法2:简单数据上的纯函数

(defn new-lib []
  {:relevant-state 1
   :last-time-called (new java.util.Date)})

(defn get-state [lib]
  (lib :relevant-state))

(defn lib-continue [lib]
  {:relevant-state (inc (lib :relevant-state))
   :last-time-called (new java.util.Date)})

演示:

stack-prj.noHiddenState> (def mylib (new-lib))
#'stack-prj.noHiddenState/mylib
stack-prj.noHiddenState> (get-state mylib)
1
stack-prj.noHiddenState> (def ml2 (lib-continue mylib))
#'stack-prj.noHiddenState/ml2
stack-prj.noHiddenState> (get-state ml2)
2

请注意,使用方法2,当用户通过get-state访问状态时,无法更新对象的私有变量。如果您需要此功能,那么方法1可以更好地满足您的需求;如果不这样做,那么方法2提供比第一种方法更干净,惯用且可维护的代码。