I have the following code:
(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表达式中使用了第二个版本,所以它会在不应该失败的地方失败(如果我没有弄错的话,我更喜欢第二个版本,因为它将在编译时评估)。我怀疑这可能与符号被命名空间限定有关?
let
来获取i
的组件。看起来像是一个有趣的练习 :-) - coredump