4

这是 Paul Graham 的 On Lisp 一书中的简化示例(类似于语法的方案)。

(define-macro (bar)
  (let ((x 10) (y '(1 2 3)) (z 'foo))
    `(list ,x `(,',z ,,@y))))

我知道,,@y应该如何工作,但不确定,',z应该如何工作,首先应该评估什么以及以什么顺序。(我知道它应该评估为符号 foo 因为它(10 (foo 1 2 3))以诡计返回,但我不确定确切的步骤是什么)。

我在 JavaScript 中的 lisp 中需要这个,我得到了结果:

(10 ((unquote z) 1 2 3))

因为它只是从左到右评估它(我只处理特殊,,和更多的逗号)。你应该如何评估这个表达式。

书中也有这样的例子:

(defmacro propmacro (propname)
   `(defmacro ,propname (obj)
       `(get ,obj ',',propname)))

应该如何',',评价?这种情况下的步骤是什么?

是否还有其他带有反引号/准引号的奇怪边缘情况?您能否展示这些示例以及应如何评估它们以及以什么顺序进行评估?

4

1 回答 1

8

工作原理,',z是这样的:

`(list ,x `(,',z ,,@y))))
          ^ ^
          |  `- this comma
           `- belongs to this backquote

',z 上面的逗号将表达式or插入到内部反引号中(quote ,z)。而 that,z又属于外部反引号。

因此, 的值z被插入到(quote ,z)make(quote <value-of-z>)中。

然后,实际上,内部反引号的行为类似于`(,'<value-of-z>).

具体来说,假设z包含列表(+ 2 2)。然后我们可以理解为外部反引号插入(+ 2 2)内部反引号产生`(,'(+ 2 2) ...)。这现在很容易理解:当内部反引号被评估时,(+ 2 2)被保护不被评估,从而产生 object ((+ 2 2) ...)

该模式,',',', ... ,',expr用于在最外层反引号的评估期间获得单个评估expr,以便该值随后通过剩余反引号嵌套的任意数量的评估轮传播,而无需进行进一步评估。这里有一种“反引号代数”在起作用,其中“逗号和引号抵消了”。

您还可以将其可视,',','...化为一种钻头,它可以挖掘嵌套层以允许您在结构中的任何位置植入文字值。例如

(defmacro super-nested-macro (arg)
  `(... `(.... `(.....`(we simply want arg down here ,',',',arg)))))

的作者super-nested-macro只想将 的值粘贴arg到模板中,位于埋在其他三个反引号中的位置。因此,通常,arg不能使用:逗号会被误解为属于最里面的反引号。

是否还有其他带有反引号/准引号的奇怪边缘情况?

反引号中的一个奇怪的边缘情况是试图拼接到一个点位置:

`(a b c . ,@foo)  ;; not allowed

`(a b c . ,foo)   ;; OK: equivalent to `(a b c ,@foo)

不确定各种实现如何处理点位置的反引号:

`(a b c . `(d e f))

这并没有真正的意义,我怀疑获得的实际结果将取决于反引号实现内部。

并非所有对象都被遍历以取消引用:

 `#c(,(sin theta) ,(cos theta)) ;; Not required by ANSI CL, oops!

这可以通过实现的扩展来工作。

于 2019-06-04T18:44:15.480 回答