From: Michael Abd-El-Malek
Subject: Creating enumerations in LISP
Date: 
Message-ID: <3915B8F4.1B055ECA@engmail.uwaterloo.ca>
I'm trying to make enumerations part of LISP, using a simple macro:

(defmacro defenumeration ( enum_name &rest items )
    `(do ((obj ,items (cdr obj))
        (count 0 (1+ count)))
        ((null obj) count)
    (defconstant (car obj) count)))

However, I get the following error (from CMU-Lisp):
Error in KERNEL::UNBOUND-SYMBOL-ERROR-HANDLER:  the variable COUNT is
unbound.

I've traced the problem to the defconstant call with "count".   To
illustrate the problem, this code also fails:
(let ((p 3.14159))
    (defconstant mike-super-pi p)) ; I get the error "p is unbound".

I couldn't get too much information from CLtL, so I was wondering if
somebody has an answer to this problem.  I'm a real beginner in macros
so please, give me all your suggestions and hard-earned lessons!
Also, while on the subject, I intend to use the "enum_name" argument to
defenumeration as a name of a structure to be created by the macro, so
that I can say:

(defenumeration fruit apple banana orange)
(setf some-fruit (make-fruit 'banana) )

Now of course, I don't do any checking that the call to make-fruit gives
a valid fruit in the enumeration.  I suppose I can check for that in
make-fruit.  Is this good LISP style though?
Thanks, in advance, for all the comments.
Michael Abd-El-Malek

From: Kalle Olavi Niemitalo
Subject: Re: Creating enumerations in LISP
Date: 
Message-ID: <iznhfc9pqib.fsf@stekt.oulu.fi>
Michael Abd-El-Malek <········@engmail.uwaterloo.ca> writes:

> I've traced the problem to the defconstant call with "count".   To
> illustrate the problem, this code also fails:
> (let ((p 3.14159))
>     (defconstant mike-super-pi p)) ; I get the error "p is unbound".

You can rewrite the macro so that it doesn't do this.  Your current
macro expands to a loop containing defconstant, and that doesn't
work.  Make the macro instead run the loop at expansion time, and
expand to a progn containing a number of defconstant forms.
From: Pekka P. Pirinen
Subject: Re: Creating enumerations in LISP
Date: 
Message-ID: <ixbt2hta7w.fsf@harlequin.co.uk>
Michael Abd-El-Malek <········@engmail.uwaterloo.ca> writes:
> I'm trying to make enumerations part of LISP, using a simple macro:
> 
> (defmacro defenumeration ( enum_name &rest items )
>     `(do ((obj ,items (cdr obj))
>         (count 0 (1+ count)))
>         ((null obj) count)
>     (defconstant (car obj) count)))
> 
> However, I get the following error (from CMU-Lisp): Error in
> KERNEL::UNBOUND-SYMBOL-ERROR-HANDLER: the variable COUNT is unbound.

That's a bug in CMU Lisp, since the standard doesn't provide for the
initial-value form of DEFCONSTANT to be evaluated at macroexpansion
time (it allows evaluation at compile time, and I think even that was
intended for top level forms only).

However, that's immaterial as that approach is never going to work,
since the first argument, (CAR OBJ), is not evaluated.  You should do
the loop in the macro expander to generate a list of DEFCONSTANTs in a
PROGN.

> I intend to use the "enum_name" argument to defenumeration as a name
> of a structure to be created by the macro, so that I can say:
>
> (defenumeration fruit apple banana orange)
> (setf some-fruit (make-fruit 'banana) )

How can it be a structure and an integer at the same time?  Well,
integer enumerations are a bad idea, anyway; it's better to have a
real type that can't be confused with integers, and a structure is a
good choice.
 
> Now of course, I don't do any checking that the call to make-fruit gives
> a valid fruit in the enumeration.  I suppose I can check for that in
> make-fruit.  Is this good LISP style though?

MAKE-FRUIT would seem to be the natural place to check it.  This kind
of additional functionality is one reason DEFSTRUCT allows you to
rename the constructor.
-- 
Pekka P. Pirinen, Harlequin Limited
The great problem with Lisp is that it is just good enough to keep us
from developing something really good.  - Alan Kay