以句点结尾的反引号符号列表

Backquote symbol list ending in period

我很好奇是否有一种方法可以在逗号插入值后以句点结束反引号符号列表。

示例代码如下:

(defparameter *things* '(book pencil shoe))
(defun inspect-item (item things)
    (if (member item things)
        `(you pick up the ,item and yeet it out the window.)
        `(only realize the truth... there is no ,item.)))

这将成功 (print (inspect-item 'book *things*)) 并生成交易品种列表 (YOU PICK UP THE BOOK AND YEET IT OUT THE WINDOW.)。在这种情况下,我假设句点是符号 WINDOW. 的一部分(使用最后一个函数确认)。

然而,这将失败 (print (inspect-item 'spoon *things*)) 声称变量 ITEM. 没有值(因为它认为名称是 item.)。在 item 和句点之间留下 space 会产生错误 illegal end of dotted list,我认为这是因为它假设我使用的是点列表语法。

有什么办法让它在最后产生我想要的符号(BOOK.)?

解决方案的可能要求

您需要在旧符号的基础上创建一个新符号:

  • 同名,附加 .
  • 可能在同一个包中

句号为符号

请注意,您可以使用转义符号将句点作为名称写入符号:|.|\.

CL-USER 17 > (let ((item 'foobar))
               `(only realize the truth... there is no ,item \.))
(ONLY REALIZE THE TRUTH... THERE IS NO FOOBAR \.)

princ 不带转义字符打印:

CL-USER 18 > (princ '(ONLY REALIZE THE TRUTH... THERE IS NO FOOBAR \.))
(ONLY REALIZE THE TRUTH... THERE IS NO FOOBAR .)       ; <- printed output
(ONLY REALIZE THE TRUTH... THERE IS NO FOOBAR \.)      ; <- REPL value

解决方案

CL-USER 19 > (defun add-suffix (symbol suffix)
               (intern (concatenate 'string
                                    (symbol-name symbol)
                                    (symbol-name suffix))
                       (symbol-package symbol)))
ADD-SUFFIX

CL-USER 20 > (let ((item 'tree))
               `(we went to the ,(add-suffix item '|.|)))
(WE WENT TO THE TREE.)

使用 format 的灵​​活性代替 concatenate 也很有用。

CL-USER 22 > (defun add-suffix (symbol suffix)
               (intern (format nil "~a~a" symbol suffix)
                       (symbol-package symbol)))
ADD-SUFFIX

我认为真正的问题在于尝试生成 文本 就像 符号列表 的印刷表示一样。这些是完全不同的事情。这样做的唯一原因可能是某种锻炼。有很多介绍性的文字会做这种事情。

相反,我建议实际生成文本,即。 e.字符串。您可能会使用非常灵活的 format 函数来插入变量:

(defparameter *things* '("book" "pencil" "shoe"))

(defun inspect-item (item things)
  (if (member item things :test #'string-equal)
      (format nil
              "You pick up the ~a and yeet it out the window."
              item)
      (format nil
              "Only realize the truth… there is no ~a."
              item)))

我部分同意 Svante 的观点,将符号列表转换为文本通常是错误的。另一方面,诸如解析器 &c 之类的东西通常希望根据符号而不是字符串来思考,因为符号具有很好的属性,例如 (eq a b) 以您希望的方式工作。

话虽这么说,但这是另一种方法:创建一个单词列表,然后使用一个函数将它们转换为表示句子的字符串,并添加适当的标点符号和大写。

(defparameter *things* '(book pencil shoe))

(defun inspect-item (item things)
  (sentencify (if (member item things)
                  `(you pick up the ,item and yeet it out the window)
                `(only realize the truth... there is no ,item))))

(defun sentencify (slist &key (question nil))
  (format nil "~{~A~^ ~}~A"
          (loop for first = t then nil
                for w in slist
                for ws = (typecase w
                           (symbol (symbol-name w))
                           (string w)
                           (t w))
                collect (typecase ws
                          (string (if first
                                      (string-capitalize ws)
                                    (string-downcase ws)))
                          (t ws)))
          (if question "?" ".")))

现在:

> (inspect-item 'book *things*)
"You pick up the book and yeet it out the window."

> (inspect-item 'bok *things*)
"Only realize the truth... there is no bok."

> (inspect-item '(x . y) *things*)
"Only realize the truth... there is no (x . y).