将 Common Lisp 中的宏参数视为(区分大小写的)字符串

Posted

技术标签:

【中文标题】将 Common Lisp 中的宏参数视为(区分大小写的)字符串【英文标题】:Treat macro arguments in Common Lisp as (case-sensitive) strings 【发布时间】:2012-03-10 00:10:34 【问题描述】:

(这是其中一件看起来应该很简单的事情,我想可能会有更好的方法)

我正在尝试定义一个宏(用于 CLISP),它接受可变数量的参数作为符号(然后将其转换为区分大小写的字符串)。

(defmacro symbols-to-words (&body body)
  `(join-words (mapcar #'symbol-name '(,@body))))

将符号转换为大写字符串,而

(defmacro symbols-to-words (&body body)
  `(join-words (mapcar #'symbol-name '(|,@body|))))

将 ,@body 视为单个符号,不进行扩展。

有什么想法吗?我认为可能有一个更简单的方法。

【问题讨论】:

【参考方案1】:

符号名称在读取器步骤中是大写的,这发生在宏扩展之前,因此您无法使用宏来影响它。您可以全局设置READTABLE-CASE,但这会影响所有代码,特别是您必须在源代码中以大写形式编写所有标准符号。 CLISP 还有一个“-modern”选项,它为标准库的名称提供小写版本,并将阅读器设置为保留大小写,但它本身是非标准的。我自己从未使用过它,所以我不确定实际适用哪些警告。

控制阅读器的另一种方法是通过阅读器宏。 Common Lisp 已经有一个读取器宏实现区分大小写字符串的语法:double quote。在不知道您为什么不使用它的情况下很难提供更多建议。

【讨论】:

【参考方案2】:

正如 Ramarren 所说,符号的大小写是在读取时确定的。不在宏展开时。

Common Lisp 有一个语法可以在不改变大小写的情况下指定符号:

|This is a symbol| - 使用竖线作为多个转义字符。

还有一个反斜杠 - 单个转义字符:

CL-USER > 'foo\bar
|FOObAR|

其他选项有:

使用不同的全局可读大小写 使用读取和保留大小写的读取宏 使用使用自己的阅读器的读取宏

另请注意,Common Lisp 中不存在类似|,@body|(其中拼接了正文)的语法。拼接仅适用于列表 - 不适用于符号名称。 |,竖线,围绕符号的字符元素。 Common Lisp Hyperspec 中的解释有点神秘:Multiple Escape Characters。

【讨论】:

以上是关于将 Common Lisp 中的宏参数视为(区分大小写的)字符串的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个在 Common Lisp 中漂亮地打印宏扩展的宏不起作用?都有哪些替代工具?

Common-Lisp:绑定形式参数,到底传递了啥?

Common Lisp 中的整数除法

Common Lisp宏变量扩展

替换 Common Lisp 列表中的项目?

Common Lisp 中的本地状态