为什么没有`unquote`Lisp原语?

时间:2013-08-29 15:37:54

标签: lisp eval quote

最近,我一直在思考Lisp的基础;我在互联网上阅读了几本手册和/或其他资料,包括P. Graham撰写的The Roots of Lisp

Lisp的根源中,quote被描述为将代码更改为数据的原语,从而引用它,但似乎没有是一个等价的反原语,即unquote原语。我认为它可能是eval的业务,但eval经常在空词法环境中运行数据,这不等同于将数据更改回代码。

Ergo,为什么不存在unquote Lisp原语?

2 个答案:

答案 0 :(得分:11)

unquote仅在quasiquote的上下文中有用,而quasiquote可以实现为宏(在幕后使用quote)。所以不需要unquote原语; quasiquote宏只会在找到符号时处理unquote符号。

quasiquote是反引号引用的Scheme名称。因此:

`(foo bar ,baz)

读入
(quasiquote (foo bar (unquote baz)))
在Scheme中


这是一个非常简单的Scheme quasiquote宏(它只处理列表,不像标准quasiquote,它也处理向量和其他数据类型):

(define-syntax quasiquote
  (syntax-rules (unquote unquote-splicing)
    ((quasiquote (unquote datum))
     datum)
    ((quasiquote ((unquote-splicing datum) . next))
     (append datum (quasiquote next)))
    ((quasiquote (datum . next))
     (cons (quasiquote datum) (quasiquote next)))
    ((quasiquote datum)
     (quote datum))))

使用所有标准读者缩写的等效版本:

(define-syntax quasiquote
  (syntax-rules (unquote unquote-splicing)
    (`,datum
     datum)
    (`(,@datum . next)
     (append datum `next))
    (`(datum . next)
     (cons `datum `next))
    (`datum
     'datum)))

答案 1 :(得分:0)

我对Lisp也比较陌生,但我认为你所考虑的是evaleval是将数据更改回代码的方法。

即,考虑一个简单的功能。

(defun foo (a b c) (list a b c))

然后,如果你做这样的事情,你会得到一个符号列表:

CL-USER> (foo 'a 'b 'c)
(A B C)

如果在前面添加引号,则函数调用本身被视为一段数据(列表):

CL-USER> '(foo 'a 'b 'c)
(FOO 'A 'B 'C)

添加一个引用会产生预期效果:

CL-USER> ''(foo 'a 'b 'c)
'(FOO 'A 'B 'C)

现在让我们用eval展开它,这实际上可以被认为是quote的逆操作。这是相反的。 x轴是数据形式。 y轴是代码形式。希望这种(有点拉伸)类比是有道理的。

CL-USER> (eval ''(foo 'a 'b 'c))
(FOO 'A 'B 'C)

如果我连续两个eval链接,你能猜出会发生什么吗? 这是:

CL-USER> (eval (eval ''(foo 'a 'b 'c)))
(A B C)