我一直试图让它与引用,引用拼接,评估以及我能想到的其他任何东西一起工作,但到目前为止还没有运气。我理解为什么它不起作用 - 它被视为一张地图,并且它试图评估a
,b
和c
- 只是没有如何解决它。
(def destructor {a :a b :b c :c})
; CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(:1:15)
(let [destructor my-map]
'etc)
我有一个相当复杂的解构图,我考虑过多次使用,所以把它藏在某个地方似乎是个好主意。也许还有更好的方法可以解决这个问题?
答案 0 :(得分:3)
好主意,但你不能这么做,因为你要存储的东西实际上不是一个值,所以你不能将它存储在var中。
相反,您可以在其扩展中定义包含此内容的宏:
(defmacro with-abc [abc & body]
`(let [~'{:keys [a b c]} ~abc]
~@body))
(with-abc foo
(...use a, b, and c...))
答案 1 :(得分:2)
像@ amalloy这样的答案也是我的第一直觉,这可能就是它的发展方向。也就是说,考虑一个简单的ol'高阶函数:
(defn destruct
[{a :a b :b c :c} f]
(f a b c))
(destruct my-map
(fn [a b c]
(println a)
(println b)
(println c)))
它有点肮脏,你每次都被迫命名绑定,但是你要避免潜在的卫生问题,并且根据你对元编程的舒适程度,它会更容易放入在一起。
答案 2 :(得分:0)
你需要引用破坏模式
(def my-destructor '{a :a b :b c :c})
您可以使用引用/取消引用的级别来执行此操作,但使用辅助函数更容易看到。
(defn- with-destructor* [binding & body]
`(let ~binding ~@body))
此eval
发生在“编译”时(宏扩展期间)
(defmacro with-destructor [[destructor form] & body]
(eval `(with-destructor* [~destructor '~form] '~@body)))
如图所示
(macroexpand-1 '(with-destructor [my-destructor {:a 1 :c 3}] (+ a c)))
;=> (clojure.core/let [{a :a, b :b, c :c} {:a 1, :c 3}] (+ a c))
结果
(with-destructor [my-destructor {:a 1 :c 3}] (+ a c))
;=> 4