在 Clojure 中,我将如何为惰性序列重新定义 vars?
In Clojure, how would I redefine vars for a lazy sequence?
在命名空间中,我有两个动态变量:
(def ^:dynamic *form-data*)
(def ^:dynamic *form-errors*)
为了快速为它们创建新的绑定,我制作了一个包装器宏:
(defmacro with-form [data errors & body]
`(binding [*form-data* ~data
*form-errors* ~errors]
~@body))
我在同一个命名空间中有几个依赖这些变量的函数,其中之一是 input-field
。
当我在 repl 中单独使用该函数时,它会起作用。但是当我这样使用它时:
(vf/with-form {} {}
(map #(vf/input-field hf/text-field %) [:name :code]))
我得到一个错误:Attempting to call unbound fn: *form-errors*
我猜问题是 bindings
运行了 map
,创建了一个惰性序列,并将变量解除绑定回到它们的原始状态。有没有办法绕过这个限制?
谢谢。
使用doall
强制实现整个lazy seq:
(vf/with-form {} {}
(doall (map #(vf/input-field hf/text-field %) [:name :code])))
binding
文档中的这个 example 说明了相同的技术。
或者,要保持惰性,请使用 bound-fn*
,如文档中的 example 所示:
(vf/with-form {} {}
(map (bound-fn* #(vf/input-field hf/text-field %)) [:name :code]))
只是为了补充之前的答案,请参阅此 list of documentation sources,尤其是 Clojure CheatSheet。
特别是,我总是喜欢使用mapv
而不是map
。相当于
(vec (map ...))
它避免了惰性序列造成的“陷阱”。
在命名空间中,我有两个动态变量:
(def ^:dynamic *form-data*)
(def ^:dynamic *form-errors*)
为了快速为它们创建新的绑定,我制作了一个包装器宏:
(defmacro with-form [data errors & body]
`(binding [*form-data* ~data
*form-errors* ~errors]
~@body))
我在同一个命名空间中有几个依赖这些变量的函数,其中之一是 input-field
。
当我在 repl 中单独使用该函数时,它会起作用。但是当我这样使用它时:
(vf/with-form {} {}
(map #(vf/input-field hf/text-field %) [:name :code]))
我得到一个错误:Attempting to call unbound fn: *form-errors*
我猜问题是 bindings
运行了 map
,创建了一个惰性序列,并将变量解除绑定回到它们的原始状态。有没有办法绕过这个限制?
谢谢。
使用doall
强制实现整个lazy seq:
(vf/with-form {} {}
(doall (map #(vf/input-field hf/text-field %) [:name :code])))
binding
文档中的这个 example 说明了相同的技术。
或者,要保持惰性,请使用 bound-fn*
,如文档中的 example 所示:
(vf/with-form {} {}
(map (bound-fn* #(vf/input-field hf/text-field %)) [:name :code]))
只是为了补充之前的答案,请参阅此 list of documentation sources,尤其是 Clojure CheatSheet。
特别是,我总是喜欢使用mapv
而不是map
。相当于
(vec (map ...))
它避免了惰性序列造成的“陷阱”。