相关疑难解决方法(0)

"透明"的宏可能吗?

我想编写一个with-test-tags包含大量表单的Clojure 宏,并在每个deftest表单的名称中添加一些元数据- 具体来说,在:tags键中添加一些东西,这样我就可以使用工具来运行具体的测试标签.

一个明显的实现with-test-tags是递归地遍历整个身体,deftest在我找到它时修改每个表单.但是我最近一直在阅读Let Over Lambda,他提出了一个很好的观点:不要自己编写代码,只需将代码包装好,macrolet然后让编译器为你完成.就像是:

(defmacro with-test-tags [tags & body]
  `(macrolet [(~'deftest [name# & more#]
                `(~'~'deftest ~(vary-meta name# update-in [:tags] (fnil into []) ~tags)
                   ~@more#))]
     (do ~@body)))

(with-test-tags [:a :b] 
  (deftest x (...do tests...)))
Run Code Online (Sandbox Code Playgroud)

但是,这有一个明显的问题,即deftest宏继续递归地递增.我可以将它扩展为clojure.test/deftest相反,从而避免任何进一步的递归扩展,但是我无法有效地嵌套with-test-tags标记子组测试的实例.

在这一点上,特别是对于简单的事情deftest,它看起来像走自己的代码会更简单.但我想知道是否有人知道编写宏的技术,它会"略微修改"某些子表达式,而不会永远递归.

对于好奇:我考虑了一些其他的方法,例如我有一个编译时binding可变的var,我设置为上下代码,并在我最终看到a时使用该var deftest,但由于每个宏只返回一个扩展它的绑定将不适用于下一次调用macroexpand.

编辑

我刚刚做了postwalk实现,虽然它工作但它不尊重特殊形式,例如quote- 它也扩展到那些内部.

(defmacro with-test-tags [tags & body]
  (cons `do
        (postwalk (fn [form]
                    (if …
Run Code Online (Sandbox Code Playgroud)

macros clojure common-lisp

15
推荐指数
1
解决办法
620
查看次数

Clojure宏创建函数的同义词

对于任何真正知道如何在任何Lisp中编写宏的人来说,这可能是一个简单的方法.我希望能够为函数名定义同义词.我一直在复制和粘贴黑客core.clj这样做,但我不想永远是这样的傻瓜!很明显,一个宏将对synoym函数的调用重写为对原始函数的调用是正确的方法.

macros clojure

6
推荐指数
1
解决办法
1016
查看次数

标签 统计

clojure ×2

macros ×2

common-lisp ×1