【发布时间】:2015-09-09 13:56:17
【问题描述】:
我有以下代码:
(ns macroo)
(def primitives #{::byte ::short ::int})
(defn primitive? [type]
(contains? primitives type))
(def pp clojure.pprint/pprint)
(defn foo [buffer data schema]
(println schema))
(defmacro write-fn [buffer schema schemas]
(let [data (gensym)]
`(fn [~data]
~(cond
(primitive? schema) `(foo ~buffer ~data ~schema)
(vector? schema) (if (= ::some (first schema))
`(do (foo ~buffer (count ~data) ::short)
(map #((write-fn ~buffer ~(second schema) ~schemas) %)
~data))
`(do ~@(for [[i s] (map-indexed vector schema)]
((write-fn buffer s schemas) `(get ~data ~i)))))
:else [schema `(primitive? ~schema) (primitive? schema)])))) ; for debugging
(pp (clojure.walk/macroexpand-all '(write-fn 0 [::int ::int] 0)))
问题是,在评估最后一个表达式时,我得到了
=>
(fn*
([G__6506]
(do
[:macroo/int :macroo/int true false]
[:macroo/int :macroo/int true false])))
如有必要,我会解释代码,但现在我只说明问题(这可能只是我犯的一个新手错误):
`(primitive? ~schema)
和
(primitive? schema)
在 :else 分支中分别返回 true 和 false,并且由于我在 cond 表达式中使用第二个版本,因此它在不应该的地方失败(我更喜欢第二个版本,因为它将在编译时进行评估时间,如果我没记错的话)。
我怀疑这可能与命名空间限定的符号有关?
【问题讨论】: