在宏lisp中生成代码

时间:2015-10-19 22:57:18

标签: macros common-lisp

我想生成代码:(nth 0 x) (nth 1 x) ... (nth n x) 其中x只是一些变量名,而n是一些数字。

我正在尝试以下列方式:

(defmacro gen(n)
    (loop for i from 1 to n do
    `(nth i x))
)

检查它如何扩展: (print (macroexpand-1 '(gen 5)))

控制台输出为:NIL。怎么做得好?

2 个答案:

答案 0 :(得分:2)

您需要将do替换为collect中的loop

但请注意,您的宏会从调用环境中捕获变量x

一般来说,“宏是高级素材”,如果你对loop不满意,你可能不应该写它们。

答案 1 :(得分:1)

考虑以下代码的值:

(loop for i from 1 to 5
   do `(nth ,i x))

由于没有收集,loop的返回值为零。如果我们将do更改为collect

(loop for i from 1 to 5
  collect `(nth ,i x))

我们看到我们正在某个地方。但是,结果列表实际上并不是有效的Common Lisp代码(并且依赖于在使用宏的环境中存在变量x。)

目前尚不清楚你想用这些做什么(只是运行它们?它们的副作用是免费的,所以只需将它包裹在progn感觉有些无用),但你需要利用prognlist或类似于列表前面的列表,使其成为有效的代码。

(defmacro gen (n &key (var 'x) (accumulator 'list))
  (cons accumulator
    (loop for i from 1 to n
      collect `(nth ,i ,var))))

这最终给了我们这个宏似乎实际上做了一些接近"有效"。