gpt4 book ai didi

list - 为什么可以在准引用列表末尾的非列表上使用取消引用拼接?

转载 作者:行者123 更新时间:2023-12-03 18:34:04 24 4
gpt4 key购买 nike

quasiquoted 列表 `(1 ,@2 3) 无效,因为 2 不是列表。但是, `(1 2 ,@3) 是有效的,将返回一个点列表: (1 2 . 3) 。我在 Common Lisp 和 Scheme 中观察到了这个结果。为什么可以在准引用列表的末尾对非列表使用 unquote-splicing?为什么结果是点线表?

最佳答案

表达式 `(1 2 ,@3) 在 Scheme 或 Common Lisp 中都无效。

方案
在 R6RS 方案(和 R5RS 类似)中,没有为使用 unquote-splicing 对非列表进行操作指定行为。 R6RS 方案标准要求 ( 11.17 Quasiquotation ):

If an (unquote-splicing <expression> ...) form appears inside a <qqtemplate>, then the <expression>s must evaluate to lists....



通用 Lisp
Common Lisp HyperSpec 首先说( 2.4.6 Backquote ):

If a comma is immediately followed by an at-sign, then the formfollowing the at-sign is evaluated to produce a list of objects.These objects are then "spliced" into place in the template.


在子表达式 ,@3 中, 3 不计算为列表。这似乎是一个非常有力的论据,即该表达式无效。即使在拼接前将 3 神奇地放在一个列表中,这也不会导致一个点列表。 HyperSpec 继续提供反引号语法的正式摘要。感兴趣的部分是:
  • `(x1 x2 x3 ... xn . atom) may be interpreted to mean

    (append [ x1] [ x2] [ x3] ... [ xn] (quote atom))

    where the brackets are used to indicate a transformation of an xj as follows:

    -- [form] is interpreted as (list `form), which contains a backquoted form that must then be further interpreted.

    -- [,form] is interpreted as (list form).

    -- [,@form] is interpreted as form.


所以在 Common Lisp 中,相当于 `(1 2 ,@3 . nil) 的原始表达式可以解释为:
(append (list `1) (list `2) 3 (quote nil))
但是,这不是对 append 的有效调用,它需要所有参数的正确列表,除了最后一个。因此,似乎不支持原始表达式有效的想法。
它适用于 Scheme 和 Common Lisp 中的 OP 的事实可能归结为不同实现中反引号宏的相似定义。这些定义似乎都期望 ,@ 后面的形式将评估为列表;如果不是这种情况,根据标准,不能依赖观察到的行为(点列表的产生)。也就是说,我测试了 Chez Scheme、Guile Scheme、MIT Scheme、SBCL、CCL 和 CLisp:它们都表现出 OP 报告的相同行为。

一个有趣的案例
我还针对 an implementation of the backquote macro by Guy Steele and published in CLTL2 进行了测试。这个案例更有趣。 CLTL2 中的这种反引号实现旨在探索反引号表达式的行为,并具有可选的代码简化阶段。这里 $ 对应反引号, %@ 对应 ,@ 。不进行代码简化,将原表达式展开的结果为:
CL-USER> (setf *bq-simplify* nil)
NIL
CL-USER> (try '("$(1 2 %@3)"))
`(1 2 ,@3) = (APPEND (LIST '1) (LIST '2) 3 'NIL)
这对应于上面通过阅读 HyperSpec 中的描述而预期的表达式。但请注意,此表达式不会编译:
CL-USER> (append (list 1) (list 2) 3 nil)

The value
3
is not of type
LIST
[Condition of type TYPE-ERROR]
但是,当打开代码简化时:
CL-USER> (setf *bq-simplify* t)
T
CL-USER> (try '("$(1 2 %@3)"))
`(1 2 ,@3) = (LIST* '1 '2 3)
这个“简化”的表达式是有效的,并计算为一个点列表:
CL-USER> (list* 1 2 3)
(1 2 . 3)
我的结论是 ,@ 后面的表达式必须是一个符合 Common Lisp 标准的列表,但一些常见的实现要么进行某种形式的代码简化,类似于 CLTL2 中所示的内容,要么以其他方式扩展反引号形式,看起来非列表形式可以跟在 ,@ 之后。不要依赖这个,因为很难说它什么时候不起作用。

关于list - 为什么可以在准引用列表末尾的非列表上使用取消引用拼接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65796899/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com