Clojure 如何将可选宏参数传递给函数
这里是Clojure宏noob。我有一个带有一些可选参数的函数,例如Clojure 如何将可选宏参数传递给函数,clojure,Clojure,这里是Clojure宏noob。我有一个带有一些可选参数的函数,例如 (defn mk-foo [name & opt] (vec (list* name opt))) 鉴于此: user> (mk-foo "bar" 1 2 3) ["bar" 1 2 3] 我正在尝试编写一个宏,它接受相同的可选参数,并将它们透明地传递给调用mk foo。到目前为止,我有: (defmacro deffoo [name & opt] `(def ~name ~(apply m
(defn mk-foo [name & opt]
(vec (list* name opt)))
鉴于此:
user> (mk-foo "bar" 1 2 3)
["bar" 1 2 3]
我正在尝试编写一个宏,它接受相同的可选参数,并将它们透明地传递给调用mk foo
。到目前为止,我有:
(defmacro deffoo [name & opt]
`(def ~name ~(apply mk-foo (str name) opt)))
达到了预期的效果:
user> (macroexpand '(deffoo bar 1 2 3))
(def bar ["bar" 1 2 3])
使用
apply
压扁列表opt
感觉很笨拙。有没有一种惯用的方法可以做到这一点?我猜需要~@
,但我不能正确引用。非常感谢。在这种情况下,您使用apply的直觉很好地帮助了您。当你有一个带引号的表单,然后把它们全部解压时,考虑把不带引号的部分移到最小的部分或列表中会有所帮助。这避免了使用代码生成可以简单编写的表单
user=> (defmacro deffoo [name & opt] `(def ~name [~(str name) ~@opt]))
#'user/deffoo
user=> (macroexpand '(deffoo "bar" 1 2 3))
(def "bar" ["bar" 1 2 3])
下面是对mk foo的呼叫:
(defmacro deffoo [name & opt] `(def ~name (mk-foo ~(str name) ~@opt)))
#'user/deffoo
user=> (macroexpand '(deffoo "bar" 1 2 3))
(def "bar" (user/mk-foo "bar" 1 2 3))
在第二种情况下,我们将
~
移动到一个级别,并让对mk foo的调用保持被引用,并且只解压缩构建参数列表所需的参数(如您所怀疑的那样使用拼接解压缩)我对clojure不是特别擅长,但对我来说它看起来不错!谢谢你迅速的回答。不幸的是,我现实生活中的mk foo比上面的插图要复杂得多。手动内联扩展它不是一个选项。我必须进行调用。从以前的一次编辑中使用mk foo恢复了该示例。此操作有效,+1,但代价是将对mk foo
的调用推迟到运行时。