Необходимость цитаты в On Lisp's #[ read macro?

Я читаю на Лиспе и не могу понять, почему в приведенном ниже коде используется кавычка. Вот выдержка из текста:

Другая комбинация символов, зарезервированная для пользователя, это # ​​[. На рисунке 17.3 приведен пример того, как этот символ может быть определен как более сложный вид левой скобки. Он определяет выражение в форме #[x y] для чтения в виде списка всех целых чисел от x до y включительно:

#[2 7]
(2 3 4 5 6 7)

Рисунок 17.3: Макрос чтения, определяющий разделители.

(set-macro-character #\] (get-macro-character #\)))

(set-dispatch-macro-character #\# #\[
                              #'(lambda (stream char1 char2)
                                   (let ((accum nil)
                                         (pair (read-delimited-list #\] stream t)))
                                     (do ((i (ceiling (car pair)) (1+ i)))
                                         ((> i (floor (cadr pair)))
                                          (list 'quote (nreverse accum)))
                                       (push i accum)))))

         Figure 17.3: A read-macro defining delimiters.

Я не понимаю, почему строка в форме результата для do** это **(список 'цитата (nreverse аккумулятор))), а не (nreverse аккумулятор). Потому что мы можем без проблем запустить код, который не использует приведенную ниже цитату, верно?

(let ((acc nil))
  (do ((i 2 (1+ i)))
      ((> i 7)
       (nreverse acc))
    (push i acc)))

Кто-нибудь знает трюк здесь?

1 ответ

Решение

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

Таким образом, у вас есть два варианта:

  1. пользователь должен написать кавычку перед интервальным выражением, чтобы предотвратить оценку
  2. вернуть цитируемый список

Здесь мы видим выбор 2.

CL-USER 7 > (read-from-string "#[5 10]")
(QUOTE (5 6 7 8 9 10))

CL-USER 8 > (eval (read-from-string "#[5 10]"))
(5 6 7 8 9 10)

CL-USER 9 > (let ((e #[5 10]))
              (describe e))

(5 6 7 8 9 10) is a LIST
0      5
1      6
2      7
3      8
4      9
5      10

Если макрос для чтения не возвращает форму списка цитат, нам нужно написать:

CL-USER 10 > (let ((e '#[5 10]))   ; notice the QUOTE
               (describe e))

(5 6 7 8 9 10) is a LIST
0      5
1      6
2      7
3      8
4      9
5      10

Хм, я бы лично предпочел последнее, написав цитату явно.

Я получил:

CL-USER 17 > '(#[5 10] #[20 25])
((QUOTE (5 6 7 8 9 10)) (QUOTE (20 21 22 23 24 25)))

Но я бы предпочел:

CL-USER 18 > '(#[5 10] #[20 25])
((5 6 7 8 9 10) (20 21 22 23 24 25))
Другие вопросы по тегам