1

この問題に遭遇しました... 非常によく似た 2 つのマクロがあります

(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

この 2 つを別のマクロに一般化して、次の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が適切に引用しないことを除いて、すべてがうまくいきます。'、 ` 、~'およびその他の多くのバリエーションなど、多くの引用および引用解除オプションを試しました。しかし、それは正しい値を与えません。

4

2 に答える 2

5

頭の中でいくつかのスコープを追跡することを気にしない場合、1 つの合理的な解決策:

(defmacro defmanagedblock [name mgr]
  `(defmacro ~name [tm# & body#]
     {:pre [(and (vector? tm#)) (= 1 (count tm#))]}
     `(let [~(first tm#) ~'~mgr]
        ~@body#)))
于 2012-09-13T03:55:53.633 に答える