"unquote" 用作准引用专有列表中倒数第二个符号时的行为

Behavior of "unquote" when used as the second to last symbol in a quasiquoted proper list

我正在尝试使用 quasiquote 生成列表 (1 unquote 2)。我试过这个:

`(1 unquote 2)

但是,在 Racket、MIT Scheme 和 Chez Scheme 中,我得到一个点列表:'(1 . 2)

所以我尝试了这个:

`(1 'unquote 2)

但是,我得到 (1 'unquote 2)

我终于用这个技巧得到了我想要的列表:

`(1 unquote 2 ,((lambda (x) x) 'unquote) 2)  ; Returns: '(1 unquote 2)

unquote 是准引用列表中的倒数第二个元素时,为什么我从准引用的正确列表中得到一个点分列表?

实际上,它并不总是产生点分列表。例如:

`(1 unquote (list 2 3 4))  ; Returns: '(1 2 3 4)

当它是准引用列表中的倒数第二个元素时,请解释这种取消引用的奇怪行为。

根据R5RS

Unpredictable behavior can result if any of the symbols quasiquote, unquote, or unquote-splicing appear in positions within a <qq template> otherwise than as described above.

并且您的职位不是“如上所述”- 表格必须是(unquote expression ...)

在 R6RS 中已升级为语法违规。

(a b c) 是 shorthand 对于 (a . (b . (c . ())))

所以 (quasiquote (1 unquote 2)) 实际上是 (quasiquote (1 . (unquote 2)))'(1 . 2).

(或者如果要完全展开,(quasiquote (1 unquote 2))就是(quasiquote . ((1 . (unquote . (2 . ()))) . ())))

类似地,(quasiquote (1 unquote (list 2 3 4)))实际上是(quasiquote (1 . (unquote (list 2 3 4)))) = (quasiquote (1 . (2 3 4))) = '(1 2 3 4).

顺便说一句,使用准引用生成 '(1 unquote 2) 的更简单方法是:

`(1 ,'unquote 2)

[写一个答案而不是评论,因为不可能在评论中正确格式化反引号。 Lisp/Scheme 仍然比降价处理得更好 ;-) ]

正如其他人所解释的(尤其是 Sorawee),unquote(又名 ,)是一个特殊名称,在 quasiquoted 列表(又名反引号)中时会受到特殊对待).为了防止它的特殊含义,一个简单的解决方法是确保特殊名称不会以文本形式出现。 请注意 unquotequote 内部没有特殊含义(与 quasiquote 内部形成对比)。

因此这将适用于 Scheme 的所有变体:

(define unquote-sym 'unquote) ; `unquote` is inside `quote`, so it's a mere symbol here

`(1 ,unquote-sym 2) ; '(1 unquote 2)