Clojure宏(如C的#define)中的文本替换功能

时间:2019-02-01 12:23:17

标签: clojure macros lisp

我想写一个宏

using Uint8 = Base<uint8_t>;
using Uint16 = Base<uint16_t>;

将在这样的地方使用

(defmacro params [] 'a 'b 'c)

如果您看到这可以通过C的#define轻松完成,只需将其替换为文本

但这只会返回一个'c

2 个答案:

答案 0 :(得分:1)

Lisp样式宏的要点是它们在 code 上操作,而不是在 text 上操作(或更具体地,在抽象语法树上操作)而不是令牌序列),这使它们比C预处理器有用得多。

您实际上打算说的是,要用三个参数调用该函数,而这三个参数恰好是每个调用站点上同名变量的值。这是很多假设。让我们看看实际情况:

(def-magic-splat-macro params    ; whatever, doesn't exist
  a b c)

(defn foo [a]
  (let [b (frob a)
        c (blah)]
    (func params)))  ; What the hell

除了模糊处理之外,我看不到这有什么用。

如果要定义标准参数:

(def standard-params [1 "quux" :never])  ; values!

(defn foo [bar]
  …
  (apply func standard-params))

答案 1 :(得分:1)

我不确定 为什么 要这样做,但是在Clojure中,通常会使用以下idom:

(defmacro with-params
  [params fncall]
  `~(concat fncall params))

(defn myfn [x y z]
  (spyx :myfn [x y z]))

(let [a 1
      b 2
      c 3]
  (println :with-params)
  (with-params [a b c]
    (myfn))

结果:

:with-params
:myfn [x y z] => [1 2 3]

但是,如果您想对代码进行硬编码以始终使用参数a,b和c,则可以执行以下操作:

(defmacro with-params-abc
  [fncall]
  `~(concat fncall '[a b c]))

(println :with-params-abc)
(with-params-abc
  (myfn))

结果:

:with-params-abc
:myfn [x y z] => [1 2 3]