【问题标题】:Backquote symbol list ending in period以句点结尾的反引号符号列表
【发布时间】:2020-02-16 14:29:11
【问题描述】:

我很好奇是否有办法用逗号插入值后的句点结束反引号符号列表。

这里是示例代码:

(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.)。在项目和句点之间留一个空格会给出错误illegal end of dotted list,我认为这是因为它假设我使用的是点列表语法。

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

【问题讨论】:

    标签: common-lisp symbols


    【解决方案1】:

    解决方案的可能要求

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

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

    句号作为符号

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

    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
    

    【讨论】:

      【解决方案2】:

      我认为真正的问题在于试图将 text 生成为 符号列表 的打印表示。这些是完全不同的事情。这样做的唯一原因可能是某种锻炼。有许多介绍性文本可以做到这一点。

      相反,我建议实际生成文本,即。 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)))
      

      【讨论】:

      • 哦,当然。这并不是一种正确的做事方式,而只是对极限的好奇探索。在任何正常情况下,您都会使用字符串。
      【解决方案3】:

      我部分同意 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).
      

      【讨论】:

        猜你喜欢
        • 2013-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-17
        • 1970-01-01
        • 1970-01-01
        • 2016-09-17
        • 2022-07-12
        相关资源
        最近更新 更多