help-gnu-emacs
[Top][All Lists]
Advanced

[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:54:10 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux)

"Pascal J. Bourguignon" <address@hidden> writes:

> address@hidden (Phillip Lord) writes:
>
>> Is it possible to build a list within a macro which contains backquote,
>> quote or comma symbols in it?
>
> Sure:
>
>     (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.

Oops, sorry, I didn't notice it was gnu.emacs.help, and not
comp.lang.lisp.

Anyways, even if emacs-lisp has a specific implementation of backquote,
I would consider it to be better style to stick to the more general
Common Lisp advice.  sbcl changed it's handling of backquote recently.
I wouldn't be surprised if emacs-lisp changed its implementation of
backquote some day too.


> 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:
>
> address@hidden :0.0 tmp]$ clall  '(loop :for item :in (quote `(,a ,b ,c)) :do 
> (print item))'
>
>
> Clozure Common Lisp:
> LIST* 
> A 
> (LIST* B (LIST C)) 
> --> NIL
>
>
> CLISP:
> SYSTEM::BACKQUOTE 
> ((SYSTEM::UNQUOTE A) (SYSTEM::UNQUOTE B) (SYSTEM::UNQUOTE C)) 
> --> NIL
>
>
> CMU Common Lisp:
> LISP::BACKQ-LIST 
> A 
> B 
> C 
> --> NIL
>
>
> ECL:
> SI:QUASIQUOTE 
> ((SI:UNQUOTE A) (SI:UNQUOTE B) (SI:UNQUOTE C)) 
> --> NIL
>
>
> SBCL:
> SB-INT:QUASIQUOTE 
> (,A ,B ,C) 
> --> NIL
>
> Notice that when printing, the implementation may cheat:
>
> address@hidden :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)))
>             clauses)))
>             
> gen-pcase
>  '(((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__                 http://www.informatimago.com/
“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]