存储解构图以供以后使用

时间:2014-05-14 02:10:21

标签: map clojure destructuring

我一直试图让它与引用,引用拼接,评估以及我能想到的其他任何东西一起工作,但到目前为止还没有运气。我理解为什么它不起作用 - 它被视为一张地图,并且它试图评估abc - 只是没有如何解决它。

(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)

我有一个相当复杂的解构图,我考虑过多次使用,所以把它藏在某个地方似乎是个好主意。也许还有更好的方法可以解决这个问题?

3 个答案:

答案 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