jcu*_*bic 4 lisp macros common-lisp lisp-macros
这是Paul Graham撰写的On Lisp上的简化示例(方案类似于语法)。
(define-macro (bar)
(let ((x 10) (y '(1 2 3)) (z 'foo))
`(list ,x `(,',z ,,@y))))
Run Code Online (Sandbox Code Playgroud)
我知道,,@y应该如何工作,但不能确切确定,',z应该如何工作,首先应该评估什么,以什么顺序进行评估。(我知道它应该评估为foo符号,因为它(10 (foo 1 2 3))以guile形式返回,但是我不确定确切的步骤是什么)。
我需要在JavaScript中使用lisp来获得结果:
(10 ((unquote z) 1 2 3))
Run Code Online (Sandbox Code Playgroud)
因为它只评估它从左到右的形式(我只处理特殊的,,逗号)。您应该如何评估此表达式。
书中也有这个例子:
(defmacro propmacro (propname)
`(defmacro ,propname (obj)
`(get ,obj ',',propname)))
Run Code Online (Sandbox Code Playgroud)
',',应该如何评估?在这种情况下应采取什么步骤?
还有其他带有反引号/准引号的怪异情况吗?您能否显示这些示例以及应如何评估它们以及以什么顺序进行示例?
它是如何,',z工作的:
`(list ,x `(,',z ,,@y))))
^ ^
| `- this comma
`- belongs to this backquote
Run Code Online (Sandbox Code Playgroud)
上面的逗号将表达式',z 或插入到内部反引号中(quote ,z)。而这,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)))))
Run Code Online (Sandbox Code Playgroud)
的作者super-nested-macro只是想将的值粘贴arg到模板中,放在其他三个反引号中。因此,,arg不能使用通常的用法:该逗号将被误解为属于最里面的反引号。
还有其他带有反引号/准引号的怪异情况吗?
反引号中一种奇怪的边缘情况是试图拼接成点位置:
`(a b c . ,@foo) ;; not allowed
`(a b c . ,foo) ;; OK: equivalent to `(a b c ,@foo)
Run Code Online (Sandbox Code Playgroud)
不确定各种实现如何处理点位置的反引号:
`(a b c . `(d e f))
Run Code Online (Sandbox Code Playgroud)
这没有任何意义,我怀疑所获得的实际结果将取决于反引号实现的内部。
并非遍历所有对象以取消引用:
`#c(,(sin theta) ,(cos theta)) ;; Not required by ANSI CL, oops!
Run Code Online (Sandbox Code Playgroud)
这可以通过实现的扩展来工作。
| 归档时间: |
|
| 查看次数: |
107 次 |
| 最近记录: |