【问题标题】:Is it legal to modify a list created using quasiquote?修改使用 quasiquote 创建的列表是否合法?
【发布时间】:2021-12-22 23:05:02
【问题描述】:

据我了解,修改使用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)

【问题讨论】:

    标签: scheme language-lawyer quasiquotes


    【解决方案1】:

    简短的回答是否定的,这不“合法”,当然这绝不应该在旨在可移植的程序中完成。 R6RS 和 R7RS 在这方面的语言几乎相同,所以我只引用R6RS, Section 11.17 Quasiquotation

    quasiquote 表达式可以返回新鲜的、可变的对象或在表达式求值期间在运行时构造的任何结构的字面量结构。不需要重建的部分总是字面的。

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

    由于在 Scheme 中尝试修改字面量是错误的,因此修改 quasiquote 表单的结果也是错误的。有时您似乎可以逃脱惩罚,但迟早会咬到您。这里真正的问题是“不需要重建的部分总是文字”。其他部分可能是字面的,也可能不是字面的。

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

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

    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) 保证是一个列表文字,因为它不需要重建在最终结果的构建中。

    【讨论】:

      猜你喜欢
      • 2014-05-12
      • 1970-01-01
      • 2019-03-15
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      • 2013-12-16
      • 2021-04-01
      • 2021-06-25
      相关资源
      最近更新 更多