我编写了一个如下所示的宏,它按预期工作,记录在运行时传递给函数的参数。
(use 'robert.hooke)
(defmacro log-func-args [func arg-log-option print-suffix]
(condp = arg-log-option
:all `(add-hook (var ~func) (fn [f# & args#]
(println "****** " (:name (meta (var ~func))) " called with "
~print-suffix args#)
(apply f# args#) ))
:first `(add-hook (var ~func) (fn [f# & args#]
(println "****** " (:name (meta (var ~func))) " called with "
~print-suffix (first args#))
(apply f# args#) ))
:rest `(add-hook (var ~func) (fn [f# & args#]
(println "****** " (:name (meta (var ~func))) " called with "
~print-suffix (rest args#))
(apply f# args#) ))
) )
然后使用它:
(log-func-args my-func-name :rest "[server,buyer]: ")
上面的宏看起来有点冗长,所以我试着重构它,以便代替多个add-hook,我只有一个内部卷入了condp,就像这样:
(defmacro log-func-args [func arg-log-option print-suffix]
`(add-hook (var ~func) (fn [f# & args#]
~(condp = arg-log-option
:all `(println "****** " (:name (meta (var ~func))) " called with "
~print-suffix args#)
:first `(println "****** " (:name (meta (var ~func))) " called with "
~print-suffix (first args#))
:rest `(println "****** " (:name (meta (var ~func))) " called with "
~print-suffix (rest args#))
)
(apply f# args#) ))
这给了我一个RuntimeException,抱怨println中的args#无法解析(因为两个语法引用形式的args#生成的符号 - 加钩形式和println形式 - 不一样) 。什么是干净的补救措施?
答案 0 :(得分:0)
使用带有let的gensym func找到一个解决方案(由Clojure编程提供)。这允许语法引用的两种形式共享相同的args符号。希望这有助于其他人。很想看到任何其他解决方案。
(defmacro log-func-args2 [func arg-log-option print-suffix]
(let [args (gensym "args")]
`(add-hook (var ~func) (fn [f# & ~args]
~(condp = arg-log-option
:all `(println "****** " (:name (meta (var ~func))) " called with "
~print-suffix ~args)
:first `(println "****** " (:name (meta (var ~func))) " called with "
~print-suffix (first ~args))
:rest `(println "****** " (:name (meta (var ~func))) " called with "
~print-suffix (rest ~args)) )
(apply f# ~args) )) ) )
答案 1 :(得分:0)
看一下potemkin的unify-gensyms
功能。它允许您使用两个哈希值(##
)而不是一个哈希值来表示应该用相同生成的符号替换的值。
跨越多种形式的gensyms越多,此解决方案就越好(与明确的let
/ gensym
形式相比)。