From: oscarpica
Subject: Using format to produce the expansion of a macro
Date: 
Message-ID: <1190678940.178580.262430@19g2000hsx.googlegroups.com>
Hi,

Is there a way to use format to produce the expansion of a macro.

If I have :
(defmacro mac(x)
  `,(format nil "(+ 10 ~d)" x))

I expansion is:
CL-USER> (macroexpand-1 '(mac 18))
"(+ 10 18)"

Obviously I would like without the double quotes
(+ 10 18)

Thanks

From: Joel Wilsson
Subject: Re: Using format to produce the expansion of a macro
Date: 
Message-ID: <1190688796.691405.238400@19g2000hsx.googlegroups.com>
On Sep 25, 2:09 am, oscarpica <············@gmail.com> wrote:
> Obviously I would like without the double quotes
> (+ 10 18)

Hello,

It's not clear to me what exactly you want.
After all your macro does return a string!
CL-USER> (mac 18)
"(+ 10 18)"

Maybe you meant to use this:
(defmacro mac2 (x)
  `(format nil "(+ 10 ~d)" ,x))

CL-USER> (mac2 18)
"(+ 10 18)"
CL-USER> (macroexpand-1 '(mac2 18))
(FORMAT NIL "(+ 10 ~d)" 18)
T

Anyways, if you want to get a list out of that string:
CL-USER> (read-from-string (macroexpand-1 '(mac 18)))
(+ 10 18)
9

But in your case the macroexpand-1 isn't even needed:
CL-USER> (read-from-string (mac 18))
(+ 10 18)
9

And if it's a list you're after, you might want:
(defmacro mac3 (x)
  `(+ 10 ,x))
CL-USER> (mac3 18)
28
CL-USER> (macroexpand-1 '(mac3 18))
(+ 10 18)

or even this:
(defmacro mac4 (x)
  `(list '+ 10 ,x)))
CL-USER> (mac4 18)
(+ 10 18)
CL-USER> (macroexpand-1 '(mac4 18))
(LIST '+ 10 18)


Regards,
  Joel
From: oscarpica
Subject: Re: Using format to produce the expansion of a macro
Date: 
Message-ID: <1190688856.760592.214720@w3g2000hsg.googlegroups.com>
I think I have found. Using read-from-string.

Or maybe there is a better way.
From: Barry Margolin
Subject: Re: Using format to produce the expansion of a macro
Date: 
Message-ID: <barmar-A2566A.02091525092007@comcast.dca.giganews.com>
In article <························@w3g2000hsg.googlegroups.com>,
 oscarpica <············@gmail.com> wrote:

> I think I have found. Using read-from-string.
> 
> Or maybe there is a better way.

Probably not.  But why are you doing this in the first place?  It 
doesn't seem to make much sense to use FORMAT when you eventually want 
to get a list.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Pascal Costanza
Subject: Re: Using format to produce the expansion of a macro
Date: 
Message-ID: <5lro7jF9p11qU1@mid.individual.net>
oscarpica wrote:
> Hi,
> 
> Is there a way to use format to produce the expansion of a macro.
> 
> If I have :
> (defmacro mac(x)
>   `,(format nil "(+ 10 ~d)" x))

Rewire your brain:

(defmacro mac (x)
   `(+ 10 ,x))


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: oscarpica
Subject: Re: Using format to produce the expansion of a macro
Date: 
Message-ID: <1190761363.048576.257780@n39g2000hsh.googlegroups.com>
On Sep 25, 2:30 am, Pascal Costanza <····@p-cos.net> wrote:
> oscarpica wrote:
> > Hi,
>
> > Is there a way to use format to produce the expansion of a macro.
>
> > If I have :
> > (defmacro mac(x)
> >   `,(format nil "(+ 10 ~d)" x))
>
> Rewire your brain:
>
> (defmacro mac (x)
>    `(+ 10 ,x))
>
> Pascal
>
> --
> My website:http://p-cos.net
> Common Lisp Document Repository:http://cdr.eurolisp.org
> Closer to MOP & ContextL:http://common-lisp.net/project/closer/

Actually i just wanted to give a simple and small example.

I don't want to use format with such a trivial case but in some cases
i find format to be very compact and useful.
From: Kent M Pitman
Subject: Re: Using format to produce the expansion of a macro
Date: 
Message-ID: <usl52rxt7.fsf@nhplace.com>
oscarpica <············@gmail.com> writes:

> Actually i just wanted to give a simple and small example.
> 
> I don't want to use format with such a trivial case but in some cases
> i find format to be very compact and useful.

Making it be about textual compactness leads to some horrible violations
of abstraction that one should never do, in part because of the time it
takes and in part because of the pontential information loss of going 
through an abstraction that is inappropriate.

Supposing that there were a function FS(content_string) which took a
a content_string and created a randomly named file with the given
name that had content_string as its contents and returned the name of
the file, and there was a function FL which took a filename, returned
its size [and, surprisingly, deleted it], would you suddenly begin to
recommend that people do
  L(F(string))
rather 
  STRING_LENGTH(string)
because it's so much more brief? Or would it trouble you that you were
communicating into and out of the file system.

Or would you compare pointers by doing a reinterpret cast of the pointer
to an integer, formatting the integer as a string, and then comparing 
strings?

Because this is what you're doing, and worse, when you use FORMAT to
expand macros.  I say worse because, unlike the comparative safety of
converting a pointer to an int in some C-like language and then
converting the number back into a pointer, where this may be reliably
safe (in some non-managed contexts that don't gc out from underneath
you in the interim), using FORMAT (or any printer operation) to
convert something to a string and then using the reader to convert it
back to an object is not idempotent, and hence is basically mangling
your data.  In general, it will make your program incorrect.

For example, you can print a gensym and you can read a gensym, but it
won't be the same object any more.

So finding a "small" example of something "wrong" is not good except in
specialized situations that cannot be meaningfully explained unless you
already know the answer because their safety involves being able to 
reason about the entire scenario and you're still trying to learn pieces
of it.

I'm guessing that at the heart of this is a fundamental misunderstanding
about the nature of either macros in lisp (that they are using text at all
to implement the backbone of their expansion, which they never are--lisp's
macros are not textual in nature and involve text only incidentally when
a particular argument to macro happens to be text) or even that the 
language definition model lisp is based on some description of how text
is parsed, which again it is not.  

Common Lisp is a language whose primitive semantics are defined on objects,
not on strings.  Text is processed by READ to produce objects, but text has
no language semantics at all.  All language semantics is defined in terms of
objects, which we notate as the text that might create them, but which might
never be there.  For example:

 (eval (cons '+ (cons 3 (cons 4 nil))))

evaluates a program that looks like

  +---+---+  +---+---+  +---+---+
  | . | .--->| . | .--->| . | / |
  +-|-+---+  +-|-+---+  +-|-+---+
    v          v          v
    +          3          4

which has no source code.  The semantics of the language are defined on this
pointer structure, not on text.  A macro that expands (FOO 3 4) into (+ 3 4)
is not written using FORMAT because that's not what it does.

 (defmacro foo (x y) `(+ ,x ,y))

is a program that turns


  +---+---+  +---+---+  +---+---+
  | . | .--->| . | .--->| . | / |
  +-|-+---+  +-|-+---+  +-|-+---+
    v          v          v
   FOO         3          4

into

  +---+---+  +---+---+  +---+---+
  | . | .--->| . | .--->| . | / |
  +-|-+---+  +-|-+---+  +-|-+---+
    v          v          v
    +          3          4

by doing

 (cons 'foo (cdr x))

not by doing some string operation.  Making it do this by first printing
 
  +---+---+  +---+---+  +---+---+
  | . | .--->| . | .--->| . | / |
  +-|-+---+  +-|-+---+  +-|-+---+
    v          v          v
   FOO         3          4

to 

  "(FOO 3 4)"

and then doing some weird (and probably unreliable) string manipulation
and then parsing the resulting

  "(+ 3 4)"

to get

  +---+---+  +---+---+  +---+---+
  | . | .--->| . | .--->| . | / |
  +-|-+---+  +-|-+---+  +-|-+---+
    v          v          v
    +          3          4

might seem clever but if the macro had instead been called with
code that resulted from:

 (let ((v (gensym)))
   `(f (foo 3 ,v) ,v))

such that the program text was
  
  +---+---+  +---+---+  +---+---+
  | . | .--->| . | .--->| . | / |
  +-|-+---+  +-|-+---+  +-|-+---+
    v          |          v
    F          |       #:G0001  <------------+
               v                             |
           +---+---+  +---+---+  +---+---+   |
           | . | .--->| . | .--->| . | / |   |
           +-|-+---+  +-|-+---+  +-|-+---+   |
             v          v          |         |
            FOO         3          +---------+
                                             

and you were to use your macro that converted (FOO 3 #:G0001) to a string,
turned it to (+ 3 #:G0001) and then re-read it, you'd get a new gensym
(with the same name but different object identity) for only that part of
your program (but that printed the same, confusing you a lot), so that your
program looked like:

  +---+---+  +---+---+  +---+---+
  | . | .--->| . | .--->| . | / |
  +-|-+---+  +-|-+---+  +-|-+---+
    v          |          v
    F          |       #:G0001
               v
           +---+---+  +---+---+  +---+---+
           | . | .--->| . | .--->| . | / |
           +-|-+---+  +-|-+---+  +-|-+---+
             v          v          v
             +          3       #:G0001

rather than what you'd wanted, which would be:

  +---+---+  +---+---+  +---+---+
  | . | .--->| . | .--->| . | / |
  +-|-+---+  +-|-+---+  +-|-+---+
    v          |          v
    F          |       #:G0001  <------------+
               v                             |
           +---+---+  +---+---+  +---+---+   |
           | . | .--->| . | .--->| . | / |   |
           +-|-+---+  +-|-+---+  +-|-+---+   |
             v          v          |         |
             +          3          +---------+

This is the relevance of my remark about idempotency, and hopefully 
illustrates why you do not want to put things into strings and then back
into objects.

As if the speed cost in doing that weren't enough.

I hope this is enough to convince you.  This point cannot be understated.
From: oscarpica
Subject: Re: Using format to produce the expansion of a macro
Date: 
Message-ID: <1190773104.691157.198290@r29g2000hsg.googlegroups.com>
On Sep 25, 9:59 pm, Kent M Pitman <······@nhplace.com> wrote:
> oscarpica <············@gmail.com> writes:
> > Actually i just wanted to give a simple and small example.
>
> > I don't want to use format with such a trivial case but in some cases
> > i find format to be very compact and useful.
>
> Making it be about textual compactness leads to some horrible violations
> of abstraction that one should never do, in part because of the time it
> takes and in part because of the pontential information loss of going
> through an abstraction that is inappropriate.
>
> Supposing that there were a function FS(content_string) which took a
> a content_string and created a randomly named file with the given
> name that had content_string as its contents and returned the name of
> the file, and there was a function FL which took a filename, returned
> its size [and, surprisingly, deleted it], would you suddenly begin to
> recommend that people do
>   L(F(string))
> rather
>   STRING_LENGTH(string)
> because it's so much more brief? Or would it trouble you that you were
> communicating into and out of the file system.
>
> Or would you compare pointers by doing a reinterpret cast of the pointer
> to an integer, formatting the integer as a string, and then comparing
> strings?
>
> Because this is what you're doing, and worse, when you use FORMAT to
> expand macros.  I say worse because, unlike the comparative safety of
> converting a pointer to an int in some C-like language and then
> converting the number back into a pointer, where this may be reliably
> safe (in some non-managed contexts that don't gc out from underneath
> you in the interim), using FORMAT (or any printer operation) to
> convert something to a string and then using the reader to convert it
> back to an object is not idempotent, and hence is basically mangling
> your data.  In general, it will make your program incorrect.
>
> For example, you can print a gensym and you can read a gensym, but it
> won't be the same object any more.
>
> So finding a "small" example of something "wrong" is not good except in
> specialized situations that cannot be meaningfully explained unless you
> already know the answer because their safety involves being able to
> reason about the entire scenario and you're still trying to learn pieces
> of it.
>
> I'm guessing that at the heart of this is a fundamental misunderstanding
> about the nature of either macros in lisp (that they are using text at all
> to implement the backbone of their expansion, which they never are--lisp's
> macros are not textual in nature and involve text only incidentally when
> a particular argument to macro happens to be text) or even that the
> language definition model lisp is based on some description of how text
> is parsed, which again it is not.
>
> Common Lisp is a language whose primitive semantics are defined on objects,
> not on strings.  Text is processed by READ to produce objects, but text has
> no language semantics at all.  All language semantics is defined in terms of
> objects, which we notate as the text that might create them, but which might
> never be there.  For example:
>
>  (eval (cons '+ (cons 3 (cons 4 nil))))
>
> evaluates a program that looks like
>
>   +---+---+  +---+---+  +---+---+
>   | . | .--->| . | .--->| . | / |
>   +-|-+---+  +-|-+---+  +-|-+---+
>     v          v          v
>     +          3          4
>
> which has no source code.  The semantics of the language are defined on this
> pointer structure, not on text.  A macro that expands (FOO 3 4) into (+ 3 4)
> is not written using FORMAT because that's not what it does.
>
>  (defmacro foo (x y) `(+ ,x ,y))
>
> is a program that turns
>
>   +---+---+  +---+---+  +---+---+
>   | . | .--->| . | .--->| . | / |
>   +-|-+---+  +-|-+---+  +-|-+---+
>     v          v          v
>    FOO         3          4
>
> into
>
>   +---+---+  +---+---+  +---+---+
>   | . | .--->| . | .--->| . | / |
>   +-|-+---+  +-|-+---+  +-|-+---+
>     v          v          v
>     +          3          4
>
> by doing
>
>  (cons 'foo (cdr x))
>
> not by doing some string operation.  Making it do this by first printing
>
>   +---+---+  +---+---+  +---+---+
>   | . | .--->| . | .--->| . | / |
>   +-|-+---+  +-|-+---+  +-|-+---+
>     v          v          v
>    FOO         3          4
>
> to
>
>   "(FOO 3 4)"
>
> and then doing some weird (and probably unreliable) string manipulation
> and then parsing the resulting
>
>   "(+ 3 4)"
>
> to get
>
>   +---+---+  +---+---+  +---+---+
>   | . | .--->| . | .--->| . | / |
>   +-|-+---+  +-|-+---+  +-|-+---+
>     v          v          v
>     +          3          4
>
> might seem clever but if the macro had instead been called with
> code that resulted from:
>
>  (let ((v (gensym)))
>    `(f (foo 3 ,v) ,v))
>
> such that the program text was
>
>   +---+---+  +---+---+  +---+---+
>   | . | .--->| . | .--->| . | / |
>   +-|-+---+  +-|-+---+  +-|-+---+
>     v          |          v
>     F          |       #:G0001  <------------+
>                v                             |
>            +---+---+  +---+---+  +---+---+   |
>            | . | .--->| . | .--->| . | / |   |
>            +-|-+---+  +-|-+---+  +-|-+---+   |
>              v          v          |         |
>             FOO         3          +---------+
>
> and you were to use your macro that converted (FOO 3 #:G0001) to a string,
> turned it to (+ 3 #:G0001) and then re-read it, you'd get a new gensym
> (with the same name but different object identity) for only that part of
> your program (but that printed the same, confusing you a lot), so that your
> program looked like:
>
>   +---+---+  +---+---+  +---+---+
>   | . | .--->| . | .--->| . | / |
>   +-|-+---+  +-|-+---+  +-|-+---+
>     v          |          v
>     F          |       #:G0001
>                v
>            +---+---+  +---+---+  +---+---+
>            | . | .--->| . | .--->| . | / |
>            +-|-+---+  +-|-+---+  +-|-+---+
>              v          v          v
>              +          3       #:G0001
>
> rather than what you'd wanted, which would be:
>
>   +---+---+  +---+---+  +---+---+
>   | . | .--->| . | .--->| . | / |
>   +-|-+---+  +-|-+---+  +-|-+---+
>     v          |          v
>     F          |       #:G0001  <------------+
>                v                             |
>            +---+---+  +---+---+  +---+---+   |
>            | . | .--->| . | .--->| . | / |   |
>            +-|-+---+  +-|-+---+  +-|-+---+   |
>              v          v          |         |
>              +          3          +---------+
>
> This is the relevance of my remark about idempotency, and hopefully
> illustrates why you do not want to put things into strings and then back
> into objects.
>
> As if the speed cost in doing that weren't enough.
>
> I hope this is enough to convince you.  This point cannot be understated.

You expressed eloquently what I was beginning to understand.

Before reading your post I had already gave up of the idea to use
FORMAT in macro. I was beginning to feel confusedly there was
something wrong with my approach.

But I am the kind of guy that learns better by trying and
understanding what's wrong with what he's doing.

Furthermore I have learn not only by my own mistakes but also by
reading your comments and those of the other posters.

I appreciate the time you took to correct me.
From: Leandro Rios
Subject: Re: Using format to produce the expansion of a macro
Date: 
Message-ID: <46f99e03$0$1346$834e42db@reader.greatnowhere.com>
oscarpica escribi�:
> Hi,
> 
> Is there a way to use format to produce the expansion of a macro.
> 
> If I have :
> (defmacro mac(x)
>   `,(format nil "(+ 10 ~d)" x))
> 
> I expansion is:
> CL-USER> (macroexpand-1 '(mac 18))
> "(+ 10 18)"
> 
> Obviously I would like without the double quotes
> (+ 10 18)
> 
> Thanks
> 

I'm not sure what you want, but what you see is the printed 
representation of a string. The double quotes are not part of it.
Try (inspect (macroexpand-1 '(mac 18))) to see what I mean.

Leandro