Common Lisp 使用两个反引号和逗号

发布于 2024-12-06 14:04:40 字数 334 浏览 1 评论 0原文

我正在学习 common lisp,我在理解两个反引号和两个逗号的用法时遇到了问题:

``(a ,,(+ 1 2))

我的意思是,我不知道为什么它被评估为:

`(A ,3)

而不是类似的东西:

`(A 3)

我正在解释自己两个逗号都被“消耗”,以便评估表单前面的两个反引号,因此没有一个逗号应该离开,但仍然有一个。 会是什么样子?

``(a ,,(+ 1 2))

仅使用列表和 '

I'm learning common lisp and I have a problem with understanding the usage of two backquotes combined with two commas:

``(a ,,(+ 1 2))

I mean, I don't have a clue why it's evaluated to:

`(A ,3)

rather than something like that:

`(A 3)

I'm explaining myself that both commas were 'consumed' in order to evaluate two backquotes in front of the form so none of the commas should've left and yet there's still one.
How would look

``(a ,,(+ 1 2))

using only list and ' ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧人哭 2024-12-13 14:04:40

从规范来看,

Common Lisp HyperSpec 关于嵌套 反引号 是这么说的:

如果反引号语法是嵌套的,则应首先展开最里面的反引号形式。这意味着如果连续出现多个逗号,则最左边的逗号属于最里面的反引号。

R5RS 方案规范还包括有关 反引号

准引用形式可以嵌套。仅对与最外层反引号出现在同一嵌套级别的未加引号的组件进行替换。嵌套级别在每个连续的准引用内增加 1,并在每个非引用内减少 1。

另请记住,每次评估只会折叠一个反引号,就像常规引用一样,它不是递归的。

实际应用的规则

要了解这三个细节如何相互作用,让我们稍微扩展一下您的示例。这个表达式...

``(a ,,(+ 1 2) ,(+ 3 4))

计算结果如下(以 SBCL 表示法):

`(A ,3 ,(+ 3 4))
  1. 左反引号折叠起来,因此 (+ 1 2) 被匹配的逗号(第 2nd< /sup> 逗号,根据 HyperSpec)。
  2. 另一方面,(+ 3 4) 没有足够的逗号来扩展(这就是 R5RS 提到的)。
  3. 只有一个反引号被折叠,因为反引号不会递归扩展。

扩展两个逗号

要摆脱另一个反引号,需要进行另一级评估:

(eval ``(a ,,(+ 1 2) ,(+ 3 4)))

两个反引号都消失了,我们留下了一个简单的列表:

(A 3 7)

From the specs

This is what the Common Lisp HyperSpec says about nested backticks:

If the backquote syntax is nested, the innermost backquoted form should be expanded first. This means that if several commas occur in a row, the leftmost one belongs to the innermost backquote.

The R5RS Scheme spec also includes these details about backticks:

Quasiquote forms may be nested. Substitutions are made only for unquoted components appearing at the same nesting level as the outermost backquote. The nesting level increases by one inside each successive quasiquotation, and decreases by one inside each unquotation.

Also keep in mind that only one backtick gets collapsed per evaluation, just like a regular quote, it's not recursive.

Rules in action

To see how these three details interact, let's expand your example a bit. This expression...

``(a ,,(+ 1 2) ,(+ 3 4))

Gets evaluated to this (in SBCL notation):

`(A ,3 ,(+ 3 4))
  1. The left backtick got collapsed, so it the (+ 1 2) got escaped by the matching comma (the 2nd comma, according to the HyperSpec).
  2. On the other hand, the (+ 3 4) didn't have enough commas to get expanded (which is what R5RS mentions).
  3. Only one backtick got collapsed, because backticks don't get recursively expanded.

Expanding both commas

To get rid of the other backtick, another level of evaluation is needed:

(eval ``(a ,,(+ 1 2) ,(+ 3 4)))

Both backticks are gone, and we're left with a plain list:

(A 3 7)
z祗昰~ 2024-12-13 14:04:40

不,两个逗号都被消耗掉了。有两层引用和两层逗号。现在有一层引用和一层逗号。事实上,GNU Common Lisp (2.44.1) 将你的表达式求值为

(list 'a 3)

That 与这完全相同

`(a ,3)

,但更明确地“求值”了两个逗号。

No, both commas were consumed. There were two levels of quoting and two levels of commas. Now there's one level of quoting and one level of commas. In fact, GNU Common Lisp (2.44.1) evaluates your expression as

(list 'a 3)

That's exactly the same thing as

`(a ,3)

but more explicitly has "evaluated" both commas.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文