Why isn't there an `unquote` Lisp primitive?

最后都变了- 提交于 2019-12-01 15:53:34

unquote is only useful in the context of quasiquote, and quasiquote can be implemented as a macro (that uses quote behind the scenes). So there's no need to have an unquote primitive; the quasiquote macro simply deals with unquote symbols as they are found.

(quasiquote is the Scheme name for the backtick quote. Thus:

`(foo bar ,baz)

is read in as

(quasiquote (foo bar (unquote baz)))

in Scheme.)


Here's a very simple Scheme quasiquote macro (it only handles lists, unlike standard quasiquote which also handles vectors and other data types):

(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))))

Equivalent version using all the standard reader abbreviations:

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

I am also relatively new to Lisp, but I think that what you were thinking about is eval. evalis the way to change data back to code.

Namely, consider a simple function.

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

Then, if you do something like this, you get a list of symbols:

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

If you add a quote in the front, the function call itself is treated as a piece of data (list):

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

Adding one more quote has an expected effect:

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

Let us now unwind it with eval, which in essence may be thought of as the inverse operation for the quote. It is the inverse. The x-axis is the data form. The y-axis is the code form. Hopefully this (somewhat stretched) analogy makes sense.

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

Can you guess what will happen if I chain two evals in a row? Here it is:

CL-USER> (eval (eval ''(foo 'a 'b 'c)))
(A B C)
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!