Macros Scheme宏-在转换中成对,但作为输出列出?
假设我在R5RS方案中有以下宏:Macros Scheme宏-在转换中成对,但作为输出列出?,macros,scheme,Macros,Scheme,假设我在R5RS方案中有以下宏: (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) 这到底是怎么回事?
(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)
这到底是怎么回事?为什么输出是一个列表而不是一对?在第二种情况下,
c
可能是(3)()
?我不确定,但这对我来说是有意义的。然后引用(ab.c)
将是(12.(3)()
,这是(12.(3))
和(3)
是一个合适的列表,所以(12.3)
?要了解这里发生了什么,您需要知道Scheme中的列表是一个由成对元素和其他列表组成的递归链。任何遵循列表形式的数据都将始终作为列表打印。一旦知道基本列表是如何构造的,就可以看到宏中发生了什么
可以使用
操作符或使用cons
功能创建方案中的对。以下是一对简单的数字:
(quote (1 . 2))
==> '(1 . 2)
(cons 1 2)
==> '(1 . 2)
要在Scheme中创建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)
要查看宏正在执行的操作,可以重新排列(引号(ab.c))
,使其更加明确:
(quote (a . (b . c)))
(cons (quote a) (cons (quote b) (quote c)))
现在您可以看到,此表单与构建列表时非常相似。如果(引号c)
生成一个列表,那么整个表达式将是一个列表。在(成对测试(1 2 3))
的情况下,c
变为(3)()
:
REPL将此值打印为列表,因为它是“正确的列表”。每个右侧(cdr
)都是一个列表,一直到最后的空列表,因此该值完全遵循列表形式。REPL假定您希望将结果显示为列表,因此打印时不显示
您将看到(12.3)
(配对测试(12.3)),因为这就是REPL打印“不正确列表”的方式。如果配对链中的最后一个元素不是空列表,则该值被视为“不正确列表”,并将以不同方式打印:
(quote (1 . (2 . 3)))
==> '(1 2 . 3)
(cons 1 (cons 2 3))
==> '(1 2 . 3)
对事实上,c是(3.()
——你不应该有额外的引号——但你基本上是对的。
(quote (1 . (2 . 3)))
==> '(1 2 . 3)
(cons 1 (cons 2 3))
==> '(1 2 . 3)