Subject: Re: Enumerations
From: rpw3@rpw3.org (Rob Warnock)
Date: Fri, 03 Feb 2006 21:58:04 -0600
Newsgroups: comp.lang.lisp
Message-ID: <McadnQ9obK_Ru3neRVn-tA@speakeasy.net>
Matt  <email@invalid.net> wrote:
+---------------
| How are enumerations typically done in Lisp?  Do you use
| keywords or symbols or what?
+---------------

Besides symbols (which includes keywords), as others have already
commented upon, sometimes people *do* use something close to C-style
enumerations, especially when the values have to be encoded into bits
of data or written to external files (or translated to C!). One example
can be found in CMUCL, in "src/compiler/generic/vm-macs.lisp":

    (defmacro defenum ((&key (prefix "") (suffix "") (start 0) (step 1))
		       &rest identifiers)
      (let ((results nil)
	    (index 0)
	    (start (eval start))
	    (step (eval step)))
	(dolist (id identifiers)
	  (when id
	    (multiple-value-bind
		(root docs)
		(if (consp id)
		    (values (car id) (cdr id))
		    (values id nil))
	      (push `(defconstant ,(intern (concatenate 'simple-string
							(string prefix)
							(string root)
							(string suffix)))
		       ,(+ start (* step index))
		       ,@docs)
		    results)))
	  (incf index))
	`(eval-when (compile load eval)
	   ,@(nreverse results))))

This is used in other parts of the compiler for such things as
assigning values to lowtag bits in objects or heap object header
types, e.g., from "src/compiler/generic/objdef.lisp":

    (in-package "VM")
    ...

    ;;; The main types.  These types are represented by the
    ;;; low three bits of the pointer or immeditate object.
    ;;; 
    (defenum (:suffix -type)
      even-fixnum
      function-pointer
      other-immediate-0
      list-pointer
      odd-fixnum
      instance-pointer
      other-immediate-1
      other-pointer)

    ;;; The heap types. Each of these types is in the header
    ;;; of objects in the heap.
    ;;; 
    (defenum (:suffix -type
	      :start (+ (ash 1 lowtag-bits) other-immediate-0-type)
	      :step (ash 1 (1- lowtag-bits)))
      bignum
      ratio
      single-float
      double-float
      complex
      complex-single-float
      complex-double-float
      
      simple-array
      simple-string
      simple-bit-vector
      ...		; [and many, many more!!]
      )

This results in DEFCONSTANTs of each name (concatenated with
the :SUFFIX value) to a distinct numeric value, e.g.:

    > (describe 'vm:function-pointer-type)

    FUNCTION-POINTER-TYPE is an external symbol in the X86 package.
    It is a constant; its value is 1.
    It is defined in:
    target:compiler/generic/objdef.lisp
    > (list vm:bignum-type
	    vm:ratio-type
	    vm:single-float-type
	    vm:double-float-type
	    vm:complex-type
	    vm:complex-single-float-type
	    vm:complex-double-float-type)
    (10 14 18 22 26 30 34)
    > 


-Rob

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607