Чтобы увидеть, что здесь происходит, вам нужно знать, что список в Scheme представляет собой рекурсивную цепочку пар элементов и других списков. Любые данные, которые соответствуют форме списка, всегда будут печататься в виде списка. Как только вы узнаете, как строятся базовые списки, вы сможете увидеть, что происходит внутри вашего макроса.
Пары в схеме могут быть созданы с помощью оператора .
или с помощью функции 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)
person
Dan Cecile
schedule
28.08.2011