From: rif
Subject: quote-removal in macros
Date: 
Message-ID: <wj0wtzjbb7a.fsf@five-percent-nation.mit.edu>
How can I define a macro which would (for example) expand

(plus 'foo 'bar)

into

(+ foo bar)

?

I can't seem to figure out how to remove the quote.

Cheers,

rif

From: Peter Lewerin
Subject: Re: quote-removal in macros
Date: 
Message-ID: <b72f3640.0408281357.2d537b8c@posting.google.com>
rif <···@mit.edu> wrote

> How can I define a macro which would (for example) expand
> (plus 'foo 'bar) => (+ foo bar)

Macro writing is a black art until you start using MACROEXPAND-1. 
With it, writing this macro would go something like this:

First try (a quasi-macro, just to see what we actually get when we
call it):

    > (defmacro plus (&rest args)
        args)
    PLUS

Expand it:

    > (macroexpand-1 '(plus 'a 'b))
    ((QUOTE A) (QUOTE B))

Aha, each argument becomes a two-element list: (QUOTE argument). 
Well, to transform ((QUOTE A) (QUOTE B)) to (A B), simply apply SECOND
to each element:

    > (defmacro plus (&rest args)
        (mapcar #'second args))
    PLUS

Expand it:

    > (macroexpand-1 '(plus 'a 'b))
    (A B)

Quotes removed, now let's make the macro return actual code:

    > (defmacro plus (&rest args)
        `(+ ,@(mapcar #'second args)))
    PLUS

Expand it:

    > (macroexpand-1 '(plus 'a 'b))
    (+ A B)

Mischief managed.
From: rif
Subject: Re: quote-removal in macros
Date: 
Message-ID: <wj0oeku6hhw.fsf@five-percent-nation.mit.edu>
> Macro writing is a black art until you start using MACROEXPAND-1. 
> With it, writing this macro would go something like this:
> 
> First try (a quasi-macro, just to see what we actually get when we
> call it):
> 
>     > (defmacro plus (&rest args)
>         args)
>     PLUS
> 
> Expand it:
> 
>     > (macroexpand-1 '(plus 'a 'b))
>     ((QUOTE A) (QUOTE B))
> 
> Aha, each argument becomes a two-element list: (QUOTE argument). 

I am familiar with the use of macroexpand-1.  However, on both OpenMCL
and CMUCL-19a, (macroexpand-1 '(plus 'a 'b)) in the above yields

('A 'B)

NOT 

((QUOTE A) (QUOTE B))

so this approach fails to directly resolve the confusion.

What is especially confusing is that at the top level (symbolp 'a)
yields T and (listp 'a) yields NIL --- it seems to be only within
macros that 'a is actually a list rather than a symbol?  As I
currently understand it, the reader translates 'a into (quote a), and
evaluation turns this back into the symbol 'A, where I don't have a
very good mental model of "turns this back into."

Cheers,

rif
From: Matthew Danish
Subject: Re: quote-removal in macros
Date: 
Message-ID: <20040828231051.GL8087@mapcar.org>
On Sat, Aug 28, 2004 at 06:10:51PM -0400, rif wrote:
> What is especially confusing is that at the top level (symbolp 'a)
> yields T and (listp 'a) yields NIL --- it seems to be only within
> macros that 'a is actually a list rather than a symbol?  As I
> currently understand it, the reader translates 'a into (quote a), and
> evaluation turns this back into the symbol 'A, where I don't have a
> very good mental model of "turns this back into."

You are confusing source code with values here.  When you talk about
symbols, do not use a ' or quote symbol, as it will only confuse you.
The printed representation for the symbol A is A, not 'A.  'A is an
alternate printed representation of the list (QUOTE A), not the symbol
A.  So naturally, functions which evaluate their arguments like symbolp
and listp will return T and NIL when supplied (QUOTE A), because QUOTE
simply returns whatever its argument is literally.  But when 'A is given
to a macro which deals with source code, the list (QUOTE A) is supplied.

So what you were trying to do originally really doesn't make much sense.
If you want the unevaluated symbols, don't make an API requiring QUOTE.
If you do want the place to be evaluated, you still do not need QUOTE to
refer to lexical variables.

The matter really comes down to your intention for the symbols.  Are
they naming variables, or are you using them for their name and symbol
properties?  These are different things: lexical variables are merely
named by symbols, they are not part of the symbol datatype in any way
whatsoever.  Lexical variables are `invisible' entities that are dealt
with behind the scenes by the compiler; the only way for a programmer to
refer to them is by using their name in the source code, which is a
symbol at compile-time.

If you are using the symbols to refer to lexical variables, then they
should appear unquoted in the source code, because programmers expect
quoted symbols to be used in the other sense.  If you are using them for
the symbol itself, it can appear either way, depending on whether you
want to allow run-time construction of symbols (or other values) or not.

-- 
;;;; Matthew Danish -- user: mrd domain: cmu.edu
;;;; OpenPGP public key: C24B6010 on keyring.debian.org
From: rif
Subject: Re: quote-removal in macros
Date: 
Message-ID: <wj0oekutwkm.fsf@five-percent-nation.mit.edu>
> So what you were trying to do originally really doesn't make much sense.
> If you want the unevaluated symbols, don't make an API requiring QUOTE.
> If you do want the place to be evaluated, you still do not need QUOTE to
> refer to lexical variables.

Understood.  In this case, I do not control the API.  I am trying to
add type declarations to slot accesses in UFFI.  The user types (for
instance)

(get-slot-value foo 'a-foo 'i)

to mean "Give me the value in the i slot in object foo, which is of
type a-foo."  Under CMUCL, this expands into:

(alien:slot foo 'i),

and the type is ignored.  Unfortunately, this generates code which (at
least in my application) is unusably inefficient.  I instead need
get-slot-value to expand to something like (the situation is somewhat
more complicated, but this gives the flavor):

(locally
   (declare (type (alien:alien a-foo) foo))
   (alien:slot foo 'i))

Note that the user of uffi:get-slot-value provides 'a-foo quoted, but
I need it unquoted in the type declaration.  I can of course avoid
this "issue" by writing directly in CMUCL's alien interface and
avoiding UFFI, but I was hoping to make the code more portable, and I
was using this as a learning experience.

Cheers,

rif
From: Christopher C. Stacy
Subject: Re: quote-removal in macros
Date: 
Message-ID: <ud61a2j3z.fsf@news.dtpq.com>
>>>>> On 29 Aug 2004 00:08:57 -0400, rif  ("rif") writes:

 >> So what you were trying to do originally really doesn't make much sense.
 >> If you want the unevaluated symbols, don't make an API requiring QUOTE.
 >> If you do want the place to be evaluated, you still do not need QUOTE to
 >> refer to lexical variables.

 rif> Understood.  In this case, I do not control the API.  I am trying to
 rif> add type declarations to slot accesses in UFFI.  The user types (for
 rif> instance)

 rif> (get-slot-value foo 'a-foo 'i)

Don't forget that he might also do (GET-SLOT-VALUE FOO 'A-FOO X)
because he programatically determined which slot he wanted.
From: Matthew Danish
Subject: Re: quote-removal in macros
Date: 
Message-ID: <20040829175112.GM8087@mapcar.org>
On Sun, Aug 29, 2004 at 01:01:51PM +0000, Christopher C. Stacy wrote:
> >>>>> On 29 Aug 2004 00:08:57 -0400, rif  ("rif") writes:
> 
>  >> So what you were trying to do originally really doesn't make much sense.
>  >> If you want the unevaluated symbols, don't make an API requiring QUOTE.
>  >> If you do want the place to be evaluated, you still do not need QUOTE to
>  >> refer to lexical variables.
> 
>  rif> Understood.  In this case, I do not control the API.  I am trying to
>  rif> add type declarations to slot accesses in UFFI.  The user types (for
>  rif> instance)
> 
>  rif> (get-slot-value foo 'a-foo 'i)
> 
> Don't forget that he might also do (GET-SLOT-VALUE FOO 'A-FOO X)
> because he programatically determined which slot he wanted.

Actually, this is an example of an API where slots are evaluated but
they shouldn't be.  I ran into this problem while designing a layer for
UFFI in CL-SDL.  At first I thought that slots could be programmatically
determined, and types, because of the API to UFFI.  Then I found out
that the macroexpansion of such forms in UFFI would not work on every
platform: you could only use literal symbols or forms.  I had to
redesign my interface not to accept anything but literal symbols or
forms after that.

-- 
;;;; Matthew Danish -- user: mrd domain: cmu.edu
;;;; OpenPGP public key: C24B6010 on keyring.debian.org
From: Coby Beck
Subject: Re: quote-removal in macros
Date: 
Message-ID: <Xy8Yc.70870$X12.50916@edtnps84>
"rif" <···@mit.edu> wrote in message
····················@five-percent-nation.mit.edu...
>
> > Macro writing is a black art until you start using MACROEXPAND-1.
> > With it, writing this macro would go something like this:
> >
> > First try (a quasi-macro, just to see what we actually get when we
> > call it):
> >
> >     > (defmacro plus (&rest args)
> >         args)
> >     PLUS
> >
> > Expand it:
> >
> >     > (macroexpand-1 '(plus 'a 'b))
> >     ((QUOTE A) (QUOTE B))
> >
> > Aha, each argument becomes a two-element list: (QUOTE argument).
>
[snip]
> What is especially confusing is that at the top level (symbolp 'a)
> yields T and (listp 'a) yields NIL --- it seems to be only within
> macros that 'a is actually a list rather than a symbol?  As I

Your test should have been:
(listp ''a)

Just remember that for a function to see what a macro will see you have to
quote it for the function.  Hence
(macro-plus 'a 'b) == (function-plus ''a ''b)
or more usually
(macro-plus a b) == (function-plus 'a 'b)

> currently understand it, the reader translates 'a into (quote a), and
> evaluation turns this back into the symbol 'A, where I don't have a
> very good mental model of "turns this back into."

Better to think of it as the quote *stops* the reader from doing anything to
it.  In both cases the reader sees A but in one case the proceeding ' stops
it from trying to see what A evaluates to.


-- 
Coby Beck
(remove #\Space "coby 101 @ big pond . com")
From: Peter Lewerin
Subject: Re: quote-removal in macros
Date: 
Message-ID: <b72f3640.0408290245.e6f6ea9@posting.google.com>
rif <···@mit.edu> wrote

> > Macro writing is a black art until you start using MACROEXPAND-1. 

> I am familiar with the use of macroexpand-1.

Sorry.  From a distance you looked just like a newbie, but now that
I've seen your later entries in this thread I realize you're not.
From: Pascal Bourguignon
Subject: Re: quote-removal in macros
Date: 
Message-ID: <87vff2p46y.fsf@thalassa.informatimago.com>
rif <···@mit.edu> writes:

> > Macro writing is a black art until you start using MACROEXPAND-1. 
> > With it, writing this macro would go something like this:
> > 
> > First try (a quasi-macro, just to see what we actually get when we
> > call it):
> > 
> >     > (defmacro plus (&rest args)
> >         args)
> >     PLUS
> > 
> > Expand it:
> > 
> >     > (macroexpand-1 '(plus 'a 'b))
> >     ((QUOTE A) (QUOTE B))
> > 
> > Aha, each argument becomes a two-element list: (QUOTE argument). 
> 
> I am familiar with the use of macroexpand-1.  However, on both OpenMCL
> and CMUCL-19a, (macroexpand-1 '(plus 'a 'b)) in the above yields
> 
> ('A 'B)
> 
> NOT 
> 
> ((QUOTE A) (QUOTE B))
> 
> so this approach fails to directly resolve the confusion.

Is there a standard way to ask the printer to print 'a as (quote a)?


CL-USER> (defun print-sexp (sexp)
  (cond ((atom sexp) (princ sexp) (princ " "))
        (t (princ "(") (mapcar (function print-sexp) sexp) (princ ")")))
  sexp)
PRINT-SEXP
CL-USER> (print-sexp (macroexpand-1 '(plus 'a 'b)))
((QUOTE A )(QUOTE B ))
('A 'B)

 
> What is especially confusing is that at the top level (symbolp 'a)
> yields T and (listp 'a) yields NIL 

CL-USER> (prog1 (values) (print-sexp '(symbolp 'a)) (print-sexp  '(listp 'a)))
(SYMBOLP (QUOTE A ))(LISTP (QUOTE A ))


> --- it seems to be only within
> macros that 'a is actually a list rather than a symbol?  As I
> currently understand it, the reader translates 'a into (quote a), and
> evaluation turns this back into the symbol 'A, where I don't have a
> very good mental model of "turns this back into."

What could be confusing is that in Lisp, expressions can be evaluated
at three different stages: 

    - at read time,
    - at compilation time,
    - at run time,

and moreover, each of these times may happen at whatever time and
recursively.


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we.
From: Rob Warnock
Subject: Re: quote-removal in macros
Date: 
Message-ID: <RKKdna-TYI4qeazcRVn-jg@speakeasy.net>
Pascal Bourguignon  <····@mouse-potato.com> wrote:
+---------------
| rif <···@mit.edu> writes:
| > I am familiar with the use of macroexpand-1.  However, on both OpenMCL
| > and CMUCL-19a, (macroexpand-1 '(plus 'a 'b)) in the above yields
| >     ('A 'B)
| > NOT 
| >     ((QUOTE A) (QUOTE B))
| > so this approach fails to directly resolve the confusion.
| 
| Is there a standard way to ask the printer to print 'a as (quote a)?
+---------------

Actually, there is! Just set or bind *PRINT-PRETTY* to NIL:

	> (let ((*print-pretty* nil))
	    (print ''a))
	(QUOTE A) 
	'A
	>


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pascal Bourguignon
Subject: Re: quote-removal in macros
Date: 
Message-ID: <87d61aos49.fsf@thalassa.informatimago.com>
····@rpw3.org (Rob Warnock) writes:

> Pascal Bourguignon  <····@mouse-potato.com> wrote:
> +---------------
> | rif <···@mit.edu> writes:
> | > I am familiar with the use of macroexpand-1.  However, on both OpenMCL
> | > and CMUCL-19a, (macroexpand-1 '(plus 'a 'b)) in the above yields
> | >     ('A 'B)
> | > NOT 
> | >     ((QUOTE A) (QUOTE B))
> | > so this approach fails to directly resolve the confusion.
> | 
> | Is there a standard way to ask the printer to print 'a as (quote a)?
> +---------------
> 
> Actually, there is! Just set or bind *PRINT-PRETTY* to NIL:
> 
> 	> (let ((*print-pretty* nil))
> 	    (print ''a))
> 	(QUOTE A) 
> 	'A
> 	>

Either the standard does not specify it, 
or clisp-2.33.2 is not conformant on this point:

CL-USER> (let ((*print-pretty* nil))
	    (print ''a))

'A 
'A


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we.
From: Pascal Bourguignon
Subject: Re: quote-removal in macros
Date: 
Message-ID: <878ybyos0j.fsf@thalassa.informatimago.com>
····@rpw3.org (Rob Warnock) writes:

> Pascal Bourguignon  <····@mouse-potato.com> wrote:
> +---------------
> | rif <···@mit.edu> writes:
> | > I am familiar with the use of macroexpand-1.  However, on both OpenMCL
> | > and CMUCL-19a, (macroexpand-1 '(plus 'a 'b)) in the above yields
> | >     ('A 'B)
> | > NOT 
> | >     ((QUOTE A) (QUOTE B))
> | > so this approach fails to directly resolve the confusion.
> | 
> | Is there a standard way to ask the printer to print 'a as (quote a)?
> +---------------
> 
> Actually, there is! Just set or bind *PRINT-PRETTY* to NIL:
> 
> 	> (let ((*print-pretty* nil))
> 	    (print ''a))
> 	(QUOTE A) 
> 	'A
> 	>

No. *PRINT-PRETTY* is specified to affect only the number of
whitespace output, not the transformation of (QUOTE A) into 'A.

------------------------------------------------------------------------
Variable *PRINT-PRETTY*

Value Type:

a generalized boolean.

Initial Value:

implementation-dependent.

Description:

Controls whether the Lisp printer calls the pretty printer.

If it is false, the pretty printer is not used and a minimum of
whitespace[1] is output when printing an expression.

If it is true, the pretty printer is used, and the Lisp printer will
endeavor to insert extra whitespace[1] where appropriate to make
expressions more readable.

*print-pretty* has an effect even when the value of *print-escape* is
 false.
------------------------------------------------------------------------


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we.
From: Paul F. Dietz
Subject: Re: quote-removal in macros
Date: 
Message-ID: <u-SdnZf3Hawxjq_cRVn-gw@dls.net>
Pascal Bourguignon wrote:

> No. *PRINT-PRETTY* is specified to affect only the number of
> whitespace output, not the transformation of (QUOTE A) into 'A.

However, when *PRINT-PRETTY* is false, the default print-object
method is used.  For CONS objects, the default method uses the
paren notation, not the ' notation.  See 22.1.3.5.

	Paul
From: Coby Beck
Subject: Re: quote-removal in macros
Date: 
Message-ID: <wJ1Yc.70028$X12.24156@edtnps84>
"rif" <···@mit.edu> wrote in message
····················@five-percent-nation.mit.edu...
>
> How can I define a macro which would (for example) expand
>
> (plus 'foo 'bar)
>
> into
>
> (+ foo bar)
>
> ?
>
> I can't seem to figure out how to remove the quote.

The likely solution is don't put them there in the first place!  As a user
of your code I would expect (based on extensive analysis of the above ;-) to
be able to just do:

(let ((foo 2))
   (plus foo (* 4 5)))

=> 22

-- 
Coby Beck
(remove #\Space "coby 101 @ big pond . com")
From: rif
Subject: Re: quote-removal in macros
Date: 
Message-ID: <wj0wtzjp70t.fsf@five-percent-nation.mit.edu>
> The likely solution is don't put them there in the first place!  As a user
> of your code I would expect (based on extensive analysis of the above ;-) to
> be able to just do:
> 
> (let ((foo 2))
>    (plus foo (* 4 5)))
> 
> => 22

I agree wholeheartedly, were I designing from scratch.  In this case,
unfortunately, I don't control the interface.  But your point is well
taken.

Cheers,

rif
From: Pascal Costanza
Subject: Re: quote-removal in macros
Date: 
Message-ID: <cgq4bi$f6l$1@newsreader3.netcologne.de>
rif wrote:

> How can I define a macro which would (for example) expand
> 
> (plus 'foo 'bar)
> 
> into
> 
> (+ foo bar)
> 
> ?
> 
> I can't seem to figure out how to remove the quote.

I am not quite sure what you are trying to achieve, but here is a shot 
at it:

(defmacro plus (&rest args)
   `(+ ,@(loop for arg in args
               when (eq (car arg) 'quote)
               collect (cadr arg))))

Note that 'foo is just shorthand for (quote foo). Internally, only the 
latter representation is used. The ' is only used for reading and printing.


Pascal

-- 
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."
From: rif
Subject: Re: quote-removal in macros
Date: 
Message-ID: <wj04qmni8su.fsf@five-percent-nation.mit.edu>
> rif wrote:
> 
> > How can I define a macro which would (for example) expand
> > (plus 'foo 'bar)
> > into
> > (+ foo bar)
> > ?
> > I can't seem to figure out how to remove the quote.
> 
> I am not quite sure what you are trying to achieve, but here is a shot
> at it:
> 

Thanks!  cadr was what I needed.

(What I am actually trying to do is rewrite a piece of uffi --- I want
get-slot-value to expand into a form that includes a type declaration
on CMUCL, for efficiency reasons.  In uffi:get-slot-value, you pass a
quoted type name, but the CMUCL type declaration requires the name
unquoted.)

Cheers,

rif
From: Karsten Poeck
Subject: Re: quote-removal in macros
Date: 
Message-ID: <Uw2Yc.111400$r4.2903740@news-reader.eresmas.com>
I don't understand what you are into, but
with
(defmacro plus (&rest args)
  (let ((filtered (mapcar #'(lambda(x)
                              (if (and (listp x)
                                       (eq 'quote (first x)))
                                  (second x)
                                x))
                          args)))
    `(+ ,@filtered)))

(let ((foo 1)
      (bar 2))
  (plus 'foo 'bar))
returns 3

"rif" <···@mit.edu> wrote in message
····················@five-percent-nation.mit.edu...
>
> How can I define a macro which would (for example) expand
>
> (plus 'foo 'bar)
>
> into
>
> (+ foo bar)
>
> ?
>
> I can't seem to figure out how to remove the quote.
>
> Cheers,
>
> rif