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

前端 未结 2 767
感情败类
感情败类 2021-01-17 12:34

Lately, I\'ve been thinking a lot about the basis of Lisp; I\'ve read several manuals and/or other materials on the Internet, including The Roots of Lisp by P. ‎Graham:

相关标签:
2条回答
  • 2021-01-17 12:56

    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)))
    
    0 讨论(0)
  • 2021-01-17 13:03

    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)
    
    0 讨论(0)
提交回复
热议问题