如何在Common Lisp中从宏参数创建单个单词?

时间:2017-01-17 05:00:12

标签: macros common-lisp

我有:

(defmacro test (a b c)
    `'(,a ,b ,c))

正常运行(test apple banana cuba)可获得(APPLE BANANA CUBA)

如何让宏制作APPLEBANANACUBA?

我试过了:

(defmacro test (a b c)
        `'(,a,b,c))

但正在运行(test ant bites chris)仍会返回(ANT BITES CHRIS)作为三个单独args的列表。

我尝试了各种变体,但似乎都没有效果。像这样:

(defmacro test (a b c)
    `(apply #'concatenate 'symbol '(,a ,b ,c)))

显然,这会出错,因为'符号不是连接的有效输出类型。

我确信这是我对宏如何工作的一些基本误解,并且有一种简单的方法可以做到这一点。我错过了什么?

2 个答案:

答案 0 :(得分:6)

将它们连接成一个字符串,然后从该字符串创建一个符号。

(defmacro test (a b c)
  (intern (concatenate 'string a b c)))

INTERN会在当前包中实习该字符串,您也可以使用MAKE-SYMBOL创建一个未加工的符号。

答案 1 :(得分:5)

对宏及其实现的困惑

  

我确信这是我对宏工作方式的一些基本误解

是:

  • 宏和创建'词'是完全独立的,正交的概念。

  • Lisp中不存在'word'的概念。但是有符号,字符串,数字......

  • 如果您考虑APPLEBANANACUBA,那么您可能意味着符号

解决问题

  1. 首先解决如何从符号列表中创建符号的问题
  2. 实现宏
  3. 如果要创建符号串联的新符号,则需要:

    1. 获取符号,将其名称作为字符串
    2. 创建一个字符串,这是这些名称的串联
    3. 从该字符串创建符号,可能在包中。
    4. 内爆手术

      让我们将此操作称为 implode ,这是它的历史名称:

      (defun implode-symbols (symbols &optional (package *package*))
        (when symbols
          (values
           (intern (with-output-to-string (stream)
                     (dolist (symbol symbols)
                       (write-string (symbol-name symbol) stream)))
                   package))))
      
      
      CL-USER 30 > (implode-symbols '(a - b - c - foo - bar))
      A-B-C-FOO-BAR
      

      现在,可以制作一个更通用的版本,它可以内爆所有内容:

      (defun implode (things)
        (when things
          (values
           (intern (with-output-to-string (stream)
                     (dolist (thing things)
                       (princ thing stream)))))))
      
      CL-USER 31 > (implode '(a - b - c - foo :bar - 42 - "BAZ"))
      A-B-C-FOOBAR-42-BAZ
      

      包含一些参数的宏

      鉴于我们是一个从事物列表中创建符号的函数,我们可以轻松编写宏:

      CL-USER 37 > (defmacro test (a b c)
                     `',(implode (list a b c)))
      TEST
      
      CL-USER 38 > (macroexpand-1 '(test foo bar baz))
      (QUOTE FOOBARBAZ)
      T
      
      CL-USER 39 > (test foo bar baz)
      FOOBARBAZ
      

      原子,爆炸和爆炸

      符号是原子。这意味着它们不是缺陷单元,它是链表的基本构建块。

      你可以爆炸和内爆原子,这里是一个符号。

      • 内爆符号FOOBAR - > FOOBAR
      • 展开符号FOOBAR - > FOOBAR