简体   繁体   English

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

[英]Text replacement capability in clojure macros like C's #define

I want to write a macro 我想写一个宏

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

that will be used in places like this 将用于这样的地方

;; without macro
(fnc a b c)

;; with macro
(fnc params) => (fnc a b c)

If you see this could be easily done by C's #define which was just a text replacement 如果您看到这可以通过C的#define轻松完成,这只是文本替换

But this just returns a 'c 但这只会返回一个'c

The point of Lisp style macros is that they operate on code , not on text (or more specific, on the abstract syntax tree instead of the token sequence ), and this makes them immensely more useful than the C preprocessor. Lisp样式宏的要点是它们对代码进行操作,而不是对文本 (或更具体而言,对抽象语法树而不是令牌序列 )进行操作,这使它们比C预处理器有用得多。

What you actually seem to intend is to say that the function is to be called with three arguments that happen to be the values of variables of the same name at each call site. 您实际上似乎打算说要用三个参数调用该函数,而这三个参数恰好是每个调用站点上同名变量的值。 That's quite a few assumptions. 这是很多假设。 Let's see how that would look in practice: 让我们看一下实际情况:

(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

I do not see how this can be useful except to obfuscate. 除了混淆之外,我看不到这有什么用。

If you want to define standard parameters: 如果要定义标准参数:

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

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

I'm not quite sure why you want to do this, but in clojure one would typically use the following idom: 我不太确定为什么要这样做,但是在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 result: 结果:

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

If, however, you want to hard-code the code to always use params a, b, and c, you could do this: 但是,如果您想对代码进行硬编码以始终使用参数a,b和c,则可以执行以下操作:

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

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

with result: 结果:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM