[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: macro-replacement with quotes

From: Pascal J. Bourguignon
Subject: Re: macro-replacement with quotes
Date: Sun, 24 Jan 2016 23:50:34 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux) (Phillip Lord) writes:

> Is it possible to build a list within a macro which contains backquote,
> quote or comma symbols in it?


    (defmacro m ()
       `(quote or comma symbols))

> Specifically, I was thinking of building a macro which expands to a
> pcase form, but I need the ` symbol in the expansion.

I assume you mean A ` symbol.  There can be a lot of different symbols
named "`", one in each different package:

(defpackage "A" (:use))
(defpackage "B" (:use))
(defpackage "C" (:use))

(list 'A::\` 'B::|`| (intern "`" "C") (intern "`" *package*))
--> (a::\` b::\` c::\` \`)

> For example, say I have a list
> '(a b c)
> which I want to expand to
> `(,a ,b ,c)

This is a problem.

'(a b c) is read as a list that contains TWO elements:
     - the symbol CL:QUOTE
     - a list of three elements (A B C).

The form '(a b c) returns the list of three elements (A B C).

On the other hand, what `(,a ,b ,c) is read as a form that is not
specified.  It can be any form that when evaluated, returns a sexp of
the same form as for example, the form (list a b c).  But it could also
be (list* a (list* b (list* c))) or some other variant.

You can introspect the form read form the backquote reader macro:

[pjb@kuiper :0.0 tmp]$ clall  '(loop :for item :in (quote `(,a ,b ,c)) :do 
(print item))'

Clozure Common Lisp:
--> NIL

--> NIL

CMU Common Lisp:
--> NIL

--> NIL

(,A ,B ,C) 
--> NIL

Notice that when printing, the implementation may cheat:

[pjb@kuiper :0.0 tmp]$ clall -r '(quote `(,a ,b ,c))'

Clozure Common Lisp            --> (LIST* A (LIST* B (LIST C)))
CLISP                          --> `(,A ,B ,C)
CMU Common Lisp                --> `(,A ,B ,C)
ECL                            --> (SI:QUASIQUOTE
                                    ((SI:UNQUOTE A) (SI:UNQUOTE B)
                                     (SI:UNQUOTE C)))
SBCL                           --> `(,A ,B ,C)

sbcl is even cheating on the printing of the unquote expressions, since
it prints a comma, instead of printing a standard representation for a
lisp object. On the other hand, the standard representation for the
unquoted objects sbcl has read from the backquote reader macro would
probably something like #<sb-internal:unquote …>; it's probably better
that it uses an implementation specific way to print this implementation
specific kind of objects.

Now the question is, given that you are given access to the internal
data structures used by the lisp interpreter or the lisp compiler
instead of a textual form, why do you want to generate a textual form to
be read again, instead of giving directly the data structure you want
the compiler to process???

> Or in full I want to expand something like
> (((a) a)
>  ((a b) a b)
>  ((a b c) a b c))
> into
> (pcase x
>   (`(,a) a)
>   (`(,a ,b) a b)
>   (`(,a ,b ,c) a b c))

I can't help here without knowing more about your PCASE macro.
>From the only example you give, I would assume that it will evaluate the
backquoted expressions. Therefore you can generate it like this:

(defun gen-pcase (clauses)
  (list* 'pcase 'x
    (mapcar (lambda (clause)
              (list* (cons 'list (first clause)) (rest clause)))
 '(((a) a)
   ((a b) a b)
   ((a b c) a b c)))
--> (pcase x
      ((list a) a)
      ((list a b) a b)
      ((list a b c) a b c))

Notice that `(,a) is read as an unspecified form that will be equivalent
to (list a), and so on.

__Pascal Bourguignon__       
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk

reply via email to

[Prev in Thread] Current Thread [Next in Thread]