unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
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:50:34 +0100	[thread overview]
Message-ID: <87mvruk2x1.fsf@kuiper.lan.informatimago.com> (raw)
In-Reply-To: mailman.2870.1453672579.843.help-gnu-emacs@gnu.org

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.

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


  parent reply	other threads:[~2016-01-24 22:50 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 [this message]
2016-01-24 22:54   ` Pascal J. Bourguignon
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=87mvruk2x1.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).