Макросы схемы - пара в преобразовании, но список в качестве вывода? - PullRequest
0 голосов
/ 28 августа 2011

Допустим, у меня есть следующий макрос в R 5 Схема RS:

(define-syntax pair-test
  (syntax-rules ()
     ((_ (a b . c))
      (quote (a b . c)))))

Макрос преобразовывает входную пару в выходную пару, как и следовало ожидать:

(pair-test (1 2 . 3))
==> (1 2 . 3)

Я также могу передать список макросу, как разрешено в спецификации. Однако на выходе получается список вместо пары:

(pair-test (1 2 3))
==> (1 2 3)

Что именно здесь происходит? Почему вывод представляет собой список вместо пары?

Ответы [ 2 ]

5 голосов
/ 28 августа 2011

Может ли c быть (3 . ()) во втором случае? Я не уверен, но это имело бы смысл для меня. И тогда кавычка (a b . c) будет (1 2 . (3 . ())), что (1 2 . (3)), а (3) - правильный список, поэтому (1 2 3)?

2 голосов
/ 28 августа 2011

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

Пары в схеме можно создать с помощью оператора . или с помощью функции cons.Вот простая пара чисел:

(quote (1 . 2))
==> '(1 . 2)
(cons 1 2)
==> '(1 . 2)

Чтобы создать список из 1 в схеме, вы можете создать из чего-то пару и пустой список:

(quote (1 . ()))
==> '(1)
(cons 1 (list))
==> '(1)

Список из2 является парой чего-то чего-то на левой стороне, и список 1 на правой стороне.Аналогично, список из 3 - это один элемент в паре со списком из 2:

(quote (1 . (2 . (3 . ()))))
==> '(1 2 3)
(cons 1 (cons 2 (cons 3 (list))))
==> '(1 2 3)

Чтобы увидеть, что делает ваш макрос, вы можете переставить (quote (a b . c)) так, чтобы он был более явным:

(quote (a . (b . c)))
(cons (quote a) (cons (quote b) (quote c)))

Теперь вы можете видеть, что эта форма очень похожа на то, когда вы создаете список.Если (quote c) приводит к списку, тогда все выражение будет списком.В случае (pair-test (1 2 3)), c становится (3 . ()):

(quote (a . (b . c)))
==> (quote (1 . (2 . (3 . ()))))
==> '(1 2 3)
(cons (quote a) (cons (quote b) (quote c)))
==> (cons '1 (cons '2 '(3 . ())))
==> '(1 2 3)

Это значение печатается в REPL в виде списка, поскольку это «правильный список».Каждая правая сторона (cdr) является списком, вплоть до пустого списка в конце, поэтому это значение полностью соответствует форме списка.REPL предполагает, что вы хотели бы видеть результат в виде списка, поэтому он печатается без . подарка.

Вы бы увидели '(1 2 . 3) для (pair-test (1 2 . 3)), потому что именно так REPLпечатает "неправильные списки".Если последний элемент в цепочке пар не является пустым списком, значение считается «неправильным списком» и будет напечатано иначе:

(quote (1 . (2 . 3)))
==> '(1 2 . 3)
(cons 1 (cons 2 3))
==> '(1 2 . 3)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...