Clojure defmacro以生成另一个defmacro
我遇到了这个问题。。。我有两个看起来非常相似的宏Clojure defmacro以生成另一个defmacro,clojure,macros,Clojure,Macros,我遇到了这个问题。。。我有两个看起来非常相似的宏 (import java.lang.management.ManagementFactory) (defmacro with-thread-manager [tm & body] {:pre [(and (vector? tm) (= 1 (count tm)))]} `(let [~(first tm) (ManagementFactory/getThreadMXBean)] ~@body)) (defmacro
(import java.lang.management.ManagementFactory)
(defmacro with-thread-manager [tm & body]
{:pre [(and (vector? tm) (= 1 (count tm)))]}
`(let [~(first tm) (ManagementFactory/getThreadMXBean)]
~@body))
(defmacro with-os-manager [tm & body]
{:pre [(and (vector? tm) (= 1 (count tm)))]}
`(let [~(first tm) (ManagementFactory/getOperatingSystemMXBean)]
~@body))
它们的用途如下:
(defn thread-count []
(with-thread-manager [tm] (.getThreadCount tm)))
(thread-count)
;; => 12
(defn application-cpu-time []
(with-os-manager [osm] (.getProcessCpuTime osm)))
(application-cpu-time)
;; => 71260000000
我希望用-*-manager将这两个宏推广到另一个宏中,以便我可以像这样简化它们:
(defmanagementblock with-thread-manager (ManagementFactory/getThreadMXBean))
(defmanagementblock with-os-manager (ManagementFactory/getOperatingSystemMXBean))
所以我知道的最简单的方法就是稍微修改一下宏
(defmacro with-thread-manager [tm & body]
{:pre [(and (vector? tm) (= 1 (count tm)))]}
(apply list 'let [(first tm) '(ManagementFactory/getThreadMXBean)]
body))
要编写块,请执行以下操作:
(defmacro defmanageblock [name MANAGER]
(list 'defmacro name '[tm & body]
'{:pre [(and (vector? tm) (= 1 (count tm)))]}
(list 'apply 'list ''let (vector '(first tm) 'MANAGER)
'body)))
一切进展顺利,只是经理没有正确报价。我尝试了一系列引用和取消引用选项,如“,”,~,以及它的许多其他变体。但是它没有给出正确的值。如果将defmanageblock定义为一个函数,该函数使用一个描述要使用的工厂的符号,该符号以列表的形式返回s表达式,那么将有两个宏调用函数,而不是嵌套的宏。在大多数情况下,在函数而不是宏中执行真正的代码生成工作会使代码更容易推理和测试如果您将defmanageblock定义为一个函数,该函数使用一个描述要使用的工厂的符号,该符号以列表形式返回s表达式,那么您将有两个宏调用函数而不是嵌套的宏. 在大多数情况下,在函数中而不是在宏中执行真正的代码生成工作会使代码更容易推理和测试一个合理的解决方案,如果您不介意在头脑中跟踪几个范围的话:
(defmacro defmanagedblock [name mgr]
`(defmacro ~name [tm# & body#]
{:pre [(and (vector? tm#)) (= 1 (count tm#))]}
`(let [~(first tm#) ~'~mgr]
~@body#)))
一个合理的解决方案,如果您不介意在脑海中记录一些范围:
(defmacro defmanagedblock [name mgr]
`(defmacro ~name [tm# & body#]
{:pre [(and (vector? tm#)) (= 1 (count tm#))]}
`(let [~(first tm#) ~'~mgr]
~@body#)))
哦,你太棒了!这就成功了。在“let[~first tm~”~mgr]行中,“and”如何工作?哦,你太棒了!这就成功了。在“let[~first tm~”~mgr]行中,“and”如何工作?