From: Reini Urban
Subject: CLHS on CASE: case key values
Date: 
Message-ID: <9fdb4c8c.0206011243.77772e6c@posting.google.com>
I'm not sure if bound symbols as case keys shouldn't use its 
symbol-value to test against. Most objects used as CASE keys are 
self-evaluating besides the special otherwise.
Esp. I really question the usefulness of the CLHS note at the end of CASE:

(case test-key
  {((key*) form*)}*)
== 
(let ((#1=#:g0001 test-key))
  (cond {((member #1# '(key*)) form*)}*))

This way you are not allowed to use symbolic constants as test keys.
For example something like:
(defconstant PCRE_ERROR_NOMATCH -1) 
...
(defun last-error (&optional (errorcode *last-error*))
  "Returns the string for the last or given pcre error code"
  (case errorcode
    (PCRE_ERROR_NOMATCH     "no match")
    (PCRE_ERROR_NULL        "null")
    (PCRE_ERROR_BADOPTION   "bad option")
    (PCRE_ERROR_BADMAGIC    "bad magic")
    (PCRE_ERROR_UNKNOWN_NODE "unknown node")
    (PCRE_ERROR_NOMEMORY    "no memory")
    (PCRE_ERROR_NOSUBSTRING "no substring")
    (otherwise nil)))

I tested another case version which checks for bound symbols:
Most of the tested CL code works fine with this variant.
Am I completely wrong?

(defmacro case (key &rest cases)
  (let* ((newsym (gensym))
	 (init `((,newsym ,key)))
	 (expr (list 'cond))
	 keylis)
    (dolist (clause cases)
      (unless (consp clause) (error "Invalid CASE clause: ~S" clause))
      (setq keylis (car clause))
      (cond
	((or (eq keylis 'otherwise) (eq keylis t))
	 (if (not (equal (list clause) (last cases)))
	     (error "CASE: the ~S clause must be the last one: ~A" clause (last cases)))
	 (push (cons t (cdr clause)) expr))
	((consp keylis)
	 (let (cases)
	   (dolist (key keylis)
	     (if (or (not (symbolp key)) (boundp key))
		 (push `(eql ,newsym ,key) cases)
		 (push `(eql ,newsym ',key) cases)))
	   (push (cons `(or ,@(nreverse cases)) (cdr clause)) expr)))
	(t
	 (if (or (not (symbolp keylis)) (boundp keylis))
	     (push (cons `(eql ,newsym ,keylis) (cdr clause)) expr)
	     (push (cons `(eql ,newsym ',keylis) (cdr clause)) expr)))))
    `(let ,init ,(nreverse expr))))

From: Paul F. Dietz
Subject: Re: CLHS on CASE: case key values
Date: 
Message-ID: <3CF9370E.6218529E@dls.net>
Reini Urban wrote:

> This way you are not allowed to use symbolic constants as test keys.
> For example something like:
> (defconstant PCRE_ERROR_NOMATCH -1)
> ...
> (defun last-error (&optional (errorcode *last-error*))
>   "Returns the string for the last or given pcre error code"
>   (case errorcode
>     (PCRE_ERROR_NOMATCH     "no match")

Use the #. reader macro:

(defun last-error (&optional (errorcode *last-error*))
  "Returns the string for the last or given pcre error code"
  (case errorcode
    (#.PCRE_ERROR_NOMATCH     "no match")

	Paul
From: Kent M Pitman
Subject: Re: CLHS on CASE: case key values
Date: 
Message-ID: <sfwy9dqwmxu.fsf@shell01.TheWorld.com>
"Paul F. Dietz" <·····@dls.net> writes:

> Reini Urban wrote:
> 
> > This way you are not allowed to use symbolic constants as test keys.
> > For example something like:
> > (defconstant PCRE_ERROR_NOMATCH -1)
> > ...
> > (defun last-error (&optional (errorcode *last-error*))
> >   "Returns the string for the last or given pcre error code"
> >   (case errorcode
> >     (PCRE_ERROR_NOMATCH     "no match")
> 
> Use the #. reader macro:
> 
> (defun last-error (&optional (errorcode *last-error*))
>   "Returns the string for the last or given pcre error code"
>   (case errorcode
>     (#.PCRE_ERROR_NOMATCH     "no match")

Prefer

(defun last-error (&optional (errorcode *last-error*))
  "Returns the string for the last or given pcre error code"
  (case errorcode
    ((#.PCRE_ERROR_NOMATCH)     "no match")
    ...))

This is more abstract just in case PCRE_ERROR_NOMATCH evaluates to a list.
Of course, it being a constant, you may think you know the value.  However,
the purpose of DEFCONSTANT is to separate the knowledge of the value from
the use of it.  If you're willing to suppose you know the value, you might
as well use -1.