From: samantha
Subject: defining a class in a macro
Date: 
Message-ID: <1141540199.516942.263070@e56g2000cwe.googlegroups.com>
The other day I found myself wanting to define classes that had
computed names.  When I attempted to define a macro to do this I ran
into difficulties.   It seemed that I needed to get from the name, a
string, to a symbol for the sake of defclass.  The thing I got to work
was weaving intern into the mix like [simplified]:

(defmacro make-cls (name)
   `(defclass ,(intern name) () () ))

This of course doesn't work for general cases.  For instance,

(let ((x "MYCLASS"))
   (make-cls x))

errors out saying x is not a string as no evaluation happens.  Putting
a "," before name causes gives a comma not in backquote error.  So how
would I do this more generally?  Probably there is something simple I
am not seeing as I am a youngling when it comes to macros.

Thanks for any help.

- s

From: KenNULLSPAMTilton
Subject: Re: defining a class in a macro
Date: 
Message-ID: <HIwOf.166$_g6.69@fe12.lga>
samantha wrote:
> The other day I found myself wanting to define classes that had
> computed names.

That sounds wrong.

>  When I attempted to define a macro to do this I ran
> into difficulties.   It seemed that I needed to get from the name, a
> string, to a symbol for the sake of defclass.  The thing I got to work
> was weaving intern into the mix like [simplified]:
> 
> (defmacro make-cls (name)
>    `(defclass ,(intern name) () () ))
> 
> This of course doesn't work for general cases.  For instance,
> 
> (let ((x "MYCLASS"))
>    (make-cls x))
> 
> errors out saying x is not a string as no evaluation happens.  Putting
> a "," before name causes gives a comma not in backquote error.  So how
> would I do this more generally?  Probably there is something simple I
> am not seeing as I am a youngling when it comes to macros.

Actually, you see it, you just don't realize that you are right: you 
cannot have it both ways. A macro arg is either evaluated or not, 
because if you try for both, how is the macro to know what is meant in 
any given case?* Your desire for "more generally" asks too much. With 
macros, it is understood that any given argument is or is not evaluated. 
In the last case, you want x in (make-cls x) evaluated. ie, "The name is 
'MYCLASS', not 'x'!!!!". Fine. But in your actual macro code you are 
evaluating  the argument name.

Since you want computed names, one might guess you want the macro to 
evaluate its class-name arg. More likely (winging it here) you want to 
embed the class-name calculation within the macro computation that 
produces the final form. Most likely, as guessed above, you should not 
be doing this at all. So...

Why are you computing class names?

kt

* There are games you can play. i do that with a debug macro, that looks 
at the first argument and expands differently if it is a string, nil, or 
anything else. But, hey, it is a /debug/ macro, it is bound to be a hack. :)
From: Bill Atkins
Subject: Re: defining a class in a macro
Date: 
Message-ID: <87lkvp5n7x.fsf@rpi.edu>
"samantha" <········@gmail.com> writes:

> The other day I found myself wanting to define classes that had
> computed names.  When I attempted to define a macro to do this I ran
> into difficulties.   It seemed that I needed to get from the name, a
> string, to a symbol for the sake of defclass.  The thing I got to work
> was weaving intern into the mix like [simplified]:
>
> (defmacro make-cls (name)
>    `(defclass ,(intern name) () () ))
>
> This of course doesn't work for general cases.  For instance,
>
> (let ((x "MYCLASS"))
>    (make-cls x))
>
> errors out saying x is not a string as no evaluation happens.  Putting
> a "," before name causes gives a comma not in backquote error.  So how
> would I do this more generally?  Probably there is something simple I
> am not seeing as I am a youngling when it comes to macros.
>
> Thanks for any help.
>
> - s

As others have mentioned, the problem is that make-cls is passed the
literal symbol X when it is expanded, not the value it is assigned at
runtime.

To see this, you can macro-expand the form (make-cls x), which will
give you:

  (defclass x () () ))

So Lisp dutifully creates a class named X, since macros are expanded
well before the (let ... ) form is actually evaluated.

HTH,
Bill Atkins
From: Pascal Bourguignon
Subject: Re: defining a class in a macro
Date: 
Message-ID: <87psl1e3d3.fsf@thalassa.informatimago.com>
"samantha" <········@gmail.com> writes:

> The other day I found myself wanting to define classes that had
> computed names.  When I attempted to define a macro to do this I ran
> into difficulties.   It seemed that I needed to get from the name, a
> string, to a symbol for the sake of defclass.  The thing I got to work
> was weaving intern into the mix like [simplified]:
>
> (defmacro make-cls (name)
>    `(defclass ,(intern name) () () ))
>
> This of course doesn't work for general cases.  For instance,
>
> (let ((x "MYCLASS"))
>    (make-cls x))
>
> errors out saying x is not a string as no evaluation happens.  Putting
> a "," before name causes gives a comma not in backquote error.  

Macros don't get their arguments evaluated.  Functions do.  If you
want to compute (at run-time) the argument, then you don't want a
macro, you want a function!   

> So how
> would I do this more generally?  Probably there is something simple I
> am not seeing as I am a youngling when it comes to macros.

(defun make-class (name) (eval `(defclass ,(intern name) () ())))

Otherwise, use MOP.


-- 
__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. -- Georges W. Bush
From: Kalle Olavi Niemitalo
Subject: Re: defining a class in a macro
Date: 
Message-ID: <87acc545lf.fsf@Astalo.kon.iki.fi>
"samantha" <········@gmail.com> writes:

> (defmacro make-cls (name)
>    `(defclass ,(intern name) () () ))
>
> This of course doesn't work for general cases.  For instance,
>
> (let ((x "MYCLASS"))
>    (make-cls x))

Is the string "MYCLASS" known at read time or compile time, or
only later (load time or run time)?  If later, then a mere macro
will not suffice; you'll need EVAL or the MOP (e.g. ENSURE-CLASS).

If only the name of the class varies, then you might also be able
to do something like:

(defmacro make-cls (name-form)
  (let ((initial-name (gensym)))
    `(progn
       (defclass ,initial-name () ())
       (let ((name ,name-form)
             (class (find-class ',initial-name)))
         (setf (find-class name) class
               (find-class ',initial-name) nil
               (class-name class) name)))))

However, I'm not sure this wouldn't violate 3.2.2.3 "Semantic Constraints".
From: samantha
Subject: Re: defining a class in a macro
Date: 
Message-ID: <1141559530.930913.201570@e56g2000cwe.googlegroups.com>
Thanks to all.  This is about what I figured.  MOP book came off my
shelf an hour before I posted.  :-)

- samantha
From: Jack Unrue
Subject: Re: defining a class in a macro
Date: 
Message-ID: <3ion02hbne2rhrlo9lv5lj774flgpog557@4ax.com>
On 5 Mar 2006 03:52:10 -0800, "samantha" <········@gmail.com> wrote:
>
> Thanks to all.  This is about what I figured.  MOP book came off my
> shelf an hour before I posted.  :-)
>
> - samantha

You've probably moved way past this issue in your
work, but let me just recommend Pascal Costanza's
Closer to MOP project:

http://common-lisp.net/project/closer/closer-mop.html

I just started using it in my code, not only to generate
classes based on computed names but also to add methods
specializing on instances of those generated classes.
It works really well (I've only tested on CLISP and
LW, but he's got support in there for several other
vendors as well).

-- 
Jack Unrue