修改使用准报价创建的列表是否合法?



据我了解,修改使用quote创建的列表是不合法的:

(let ((numbers '(3 2 1)))
(set-car! numbers 99)  ; Illegal.
numbers)

使用quasiquote创建的列表呢?修改使用quasiquote创建的列表是否合法?

(let ((numbers `(3 2 1)))
(set-car! numbers 99)  ; Legal?
numbers)
(let ((numbers `(,(+ 1 2) 2 1)))
(set-car! numbers 99)  ; Legal?
numbers)

简短的回答是否定的,这不是"合法的",当然这不应该在旨在可移植的程序中完成。R6RS 和 R7RS 对此有几乎相同的语言,所以我只引用 R6RS 第 11.17 节准引用:

quasiquote表达式可以为在表达式计算期间在运行时构造的任何结构返回新的可变对象或文本结构。不需要重建的部分始终是文字。

R7RS的第4.2.8节具有相同的语言,只是它说">新分配"而不是">新鲜"。

由于尝试修改 Scheme 中的文字是错误的,因此修改quasiquote形式的结果是错误的。有时你似乎可以侥幸逃脱,但它迟早会咬你。这里真正的问题是">不需要重建的部分总是字面意思"。其他部分可能是也可能不是字面意思。

更具体地说,对于 OP 发布的代码,`(3 2 1)保证通过 R6RS 第 11.17 节中描述的quasiquote语义计算为列表文字:

语义:如果中没有出现unquoteunquote-splicing表单,则评估(quasiquote <qq template>)的结果等同于评估(quote <qq template>)的结果。

R7RS 在第 4.2.8 节中包含类似的语言。由于(quote (3 2 1))创建列表文本,因此表达式`(3 2 1)还必须计算为列表文本。

另一方面,OP 代码`(,(+ 1 2) 2 1)必须计算(+ 1 2)并将该结果插入到生成的结构中。在这种情况下,unquote通过,运算符使用,因此生成的列表结构可能是也可能不是列表文本。

再举一个例子,考虑准引号表达式`(,(+ 1 2) (2 1))。这里的主要结果是一个列表结构,它可能是也可能不是列表文字,但结果结构的元素(2 1)保证是列表文字,因为它不需要在最终结果的构造中重建。

相关内容

  • 没有找到相关文章

最新更新