首页 > 解决方案 > 修改使用 quasiquote 创建的列表是否合法?

问题描述

据我了解,修改使用以下命令创建的列表是不合法的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)

标签: schemelanguage-lawyerquasiquotes

解决方案


The short answer is no, this isn't "legal", and certainly this should never be done in a program that aims to be portable. R6RS and R7RS have almost identical language around this, so I'll just quote from R6RS, Section 11.17 Quasiquotation:

A quasiquote expression may return either fresh, mutable objects or literal structure for any structure that is constructed at run time during the evaluation of the expression. Portions that do not need to be rebuilt are always literal.

Section 4.2.8 of R7RS has the same language, except that it says "newly allocated" instead of "fresh".

Since it is an error to attempt to modify literals in Scheme, it is an error to modify the result of a quasiquote form. This is something that you may seem get away with sometimes, but it will bite you sooner or later. The real catch here is that "portions that do not need to be rebuilt are always literal". Other portions may or may not be literal.

More specifically for OP posted code, `(3 2 1) is guaranteed to evaluate to a list literal by the semantics of quasiquote described in Section 11.17 of R6RS:

Semantics: If no unquote or unquote-splicing forms appear within the <qq template>, the result of evaluating (quasiquote <qq template>) is equivalent to the result of evaluating (quote <qq template>).

R7RS contains similar language in Section 4.2.8. Since (quote (3 2 1)) creates a list literal, the expression `(3 2 1) must also evaluate to a list literal.

On the other hand, OP code `(,(+ 1 2) 2 1) must evaluate (+ 1 2) and insert that result into the resulting structure. In this case, unquote is used via the , operator, so the resulting list structure may or may not be a list literal.

To take one more example, consider the quasiquoted expression `(,(+ 1 2) (2 1)). Here the main result is a list structure which may or may not be a list literal, but the element (2 1) of the resulting structure is guaranteed to be a list literal since it does not need to be rebuilt in the construction of the final result.


推荐阅读