如何编写具有递增ID的clojure工厂函数?

时间:2013-03-02 01:15:25

标签: clojure

我想写这样的东西(不工作):

(defn new-connection []
  (let [c (atom 0)]
    {:id #(swap! c inc)
    :writebuf (ByteBuffer/allocate 8096)
    :readbuf (ByteBuffer/allocate 8096)}))

这样我可以使用(new-connection)逐步获取id'd映射,我是否需要单独定义计数器,还是有办法用这个函数内联它?

2 个答案:

答案 0 :(得分:2)

这是一个非常普遍的问题。如果你稍微分解一下你会发现你需要三件事:1)创建新计数器的东西2)连接计数器3)新的连接函数接受id为param而不是调用计数器本身就是这个函数更一般。

(defn new-counter []
  (partial apply swap! (atom 0) inc []))

(def connection-counter (new-counter))

(defn new-connection [id]
    {:id id
    :writebuf (ByteBuffer/allocate 8096)
    :readbuf (ByteBuffer/allocate 8096)})

现在您可以使用它:

(new-connection (connection-counter))

答案 1 :(得分:1)

您可以使用closure机制“内联”计数器:

(let [c (atom 0)]
  (defn new-connection []
    {:id (swap! c inc)
     :writebuf :ByteBuffer
     :readbuf :ByteBuffer})
  (defn get-counter []
    @c))

(get-counter)
=> 0

(new-connection)
=> {:id 1, :writebuf :ByteBuffer, :readbuf :ByteBuffer}

(new-connection)
=> {:id 2, :writebuf :ByteBuffer, :readbuf :ByteBuffer}

(get-counter)
=> 2

或者如果您需要控制计数器起始值:

(defn create-connection-fn [init-counter-value]
  (let [c (atom init-counter-value)]
    (fn []
      {:id (swap! c inc)
       :writebuf :ByteBuffer
       :readbuf :ByteBuffer})))

(def new-connection (create-connection-fn 10))

(new-connection)
=> {:id 11, :writebuf :ByteBuffer, :readbuf :ByteBuffer}

(new-connection)
=> {:id 12, :writebuf :ByteBuffer, :readbuf :ByteBuffer}

编辑。如果没有理由“隐藏”它,我建议您将计数器定义为单独的变量。