Список символов обратной цитаты, заканчивающийся точкой - PullRequest
0 голосов
/ 20 октября 2019

Мне любопытно, есть ли способ завершить список символов, заключенных в кавычки, точкой, следующей за введенным запятой значением.

Вот пример кода:

(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.)?

Ответы [ 3 ]

4 голосов
/ 20 октября 2019

Возможные требования к решению

Вам необходимо создать новый символ на основе старого:

  • с тем же именем, с . добавлено
  • возможно в том же пакете

Точка как символ

Обратите внимание, что вы можете написать символ с точкой какимя с использованием экранированного символа: |.| или \..

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

princ печать без escape-символов:

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
3 голосов
/ 20 октября 2019

Я думаю, что реальная проблема заключается в попытке создать текст так же, как печатное представление списка символов . Это совершенно разные вещи. Единственной причиной, по которой это можно сделать, может быть какое-то упражнение. Существует целый ряд вводных текстов, которые делают подобные вещи.

Вместо этого я бы посоветовал на самом деле создавать текст, то есть строки. Вы можете использовать функцию 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)))
1 голос
/ 22 октября 2019

Я частично согласен со Сванте в том, что превращение списков символов в текст часто неправильно. С другой стороны, такие вещи, как синтаксические анализаторы и 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).
...