【问题标题】:defmacro to generate another defmacrodefmacro 生成另一个 defmacro
【发布时间】:2012-09-15 01:02:53
【问题描述】:

我遇到了这个问题...我有两个看起来非常相似的宏

(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

我希望将这两个with-*-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)))

一切都很顺利,除了 MANAGER 没有正确引用。我尝试了一堆引用和取消引用选项,例如 ' 、 ` 、 ~' 以及它的许多其他变体。但它没有给出正确的值。

【问题讨论】:

    标签: clojure macros


    【解决方案1】:

    一个合理的解决方案,如果您不介意在脑海中跟踪几个范围:

    (defmacro defmanagedblock [name mgr]
      `(defmacro ~name [tm# & body#]
         {:pre [(and (vector? tm#)) (= 1 (count tm#))]}
         `(let [~(first tm#) ~'~mgr]
            ~@body#)))
    

    【讨论】:

    • 哦,你摇滚!那成功了。 ` 和 ' 在 `(let [~(first tm#) ~'~mgr]...) 行的情况下如何工作?
    【解决方案2】:

    如果您将 defmanageblock 定义为一个函数,该函数接受一个描述要使用的工厂的符号,该符号将 s 表达式作为列表返回,那么您将有 两个调用函数而不是嵌套宏的宏。在大多数情况下,在函数而不是宏中进行真正的代码生成工作会使代码更容易推理和测试

    【讨论】:

      猜你喜欢
      • 2011-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-06
      • 2021-04-03
      • 1970-01-01
      • 2011-04-09
      • 2021-03-08
      相关资源
      最近更新 更多