From: "Pascal J. Bourguignon" <pjb@informatimago.com>
To: help-gnu-emacs@gnu.org
Subject: Re: macro-replacement with quotes
Date: Sun, 24 Jan 2016 23:54:10 +0100 [thread overview]
Message-ID: <87fuxmk2r1.fsf@kuiper.lan.informatimago.com> (raw)
In-Reply-To: 87mvruk2x1.fsf@kuiper.lan.informatimago.com
"Pascal J. Bourguignon" <pjb@informatimago.com> writes:
> phillip.lord@russet.org.uk (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:
>
> [pjb@kuiper :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:
>
> [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)))
> 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
next prev parent reply other threads:[~2016-01-24 22:54 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <mailman.2870.1453672579.843.help-gnu-emacs@gnu.org>
2016-01-24 22:45 ` macro-replacement with quotes Joost Kremers
2016-01-24 22:50 ` Pascal J. Bourguignon
2016-01-24 22:54 ` Pascal J. Bourguignon [this message]
2016-01-24 23:08 ` Joost Kremers
2016-01-25 19:52 ` Pascal J. Bourguignon
2016-01-24 21:56 Phillip Lord
2016-01-24 22:26 ` Marcin Borkowski
2016-01-25 10:17 ` Phillip Lord
2016-01-25 11:10 ` Marcin Borkowski
2016-01-25 14:02 ` Phillip Lord
2016-01-25 14:35 ` Michael Heerdegen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87fuxmk2r1.fsf@kuiper.lan.informatimago.com \
--to=pjb@informatimago.com \
--cc=help-gnu-emacs@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).