【发布时间】:2014-04-08 15:20:59
【问题描述】:
我想构建一个要在 Redis 管道中执行的操作列表。我正在使用accession,因为它比carmine 简单得多,但现在我需要连接池(加入时丢失),因此我再次查看胭脂红(这似乎是redis 的首选和最完整的clojure 库)
我设法让这个工作:
; require [taoensso.carmine :as redis]
(defn execute1 [request] (redis/wcar {} (eval request)))
(defmacro execute [body] `(redis/wcar {} ~@(eval body)))
(def get1 `(redis/get 1))
(execute1 get1)
(execute [get1])
但鉴于我将构建数千个元素的向量,我有点担心eval 可能会影响性能(除了我一直被教导要如果可能,避免评估)。我认为 defmacro 是/可以在宏扩展时进行评估,这可能更早(在 AOT 编译期间?)并且不使用 eval。
有什么我可以做的吗?我应该搬到另一个图书馆吗?
(我查看了 carmine 的源代码:我的痛苦只是由于作者的一点点方便:*context* 用于避免传递一些额外的参数:摆脱它应该很简单,但我没有足够的投入......我可能会决定在未来转移到另一个数据存储)
编辑:我被要求写一个我认为是我希望避免在实际代码中编写的样板的示例,所以:(以下内容未经测试,它是只是一个 POC)
(defn hset [id key val]
#(redis/hset id key val))
(defn hsetnx [id key val]
#(redis/hsetnx id key val))
(defn hincrby [id key increment]
#(redis/hincrby id key increment))
(defn hgetall [id key]
#(redis/hgetall id key))
(defn sadd [id el]
#(redis/sadd id el))
(defn scard [id]
#(redis/scard id))
(defn smembers [id]
#(redis/smembers id))
(defmacro execute [forms]
`(redis/wcar {} ~@(map apply forms)))
; end boilerplate
(defn munge-element [[a b c]]
(conj
(mapcat #(hincrby a :whatever %) b)
(sadd c b)
(hsetnx a c))
(defn flush-queue! [queue_]
(execute queue_)
[])
(defn receive [item]
(if (< (count @queue) 2000)
(swap! queue conj (munge-element item))
(swap! queue flush-queue!)))
显然,我可以写这样的东西,但如果这确实是使用胭脂红的预期方式,那么这些柯里化函数将与(或代替)普通函数一起提供。通过使用语法引用构建 defs 也可以减少很多行,但这是偶然的复杂性,而不是原始问题所固有的。
【问题讨论】: