From: David Wragg
Subject: (case 'quote ('lambda 1) (otherwise 2))
Date: 
Message-ID: <1170107293.099352.111690@j27g2000cwj.googlegroups.com>
I have found 2 Common Lisp implementations that think that the above 
code evaluates to 1.  This is quite surprising to me.

SBCL 1.0.2 (on Fedora Core 6 x86-64, from the extras repository)
* (case 'quote ('lambda 1) (otherwise 2))
[...]
1

CLisp 2.41 (as above):
[1]> (case 'quote ('lambda 1) (otherwise 2))
1

Both implementations give less surprising results for (eq 'quote 
'lambda) and (case 'lambda ('quote 1) (otherwise 2)).

Is this the correct behavior (and if so, where should I look in the 
Hyperspec to understand it)?  Or do these independent implementations 
share an obscure bug?

From: Greg Buchholz
Subject: Re: (case 'quote ('lambda 1) (otherwise 2))
Date: 
Message-ID: <1170109595.538647.154500@v45g2000cwv.googlegroups.com>
David Wragg wrote:
> I have found 2 Common Lisp implementations that think that the above
> code evaluates to 1.  This is quite surprising to me.
>
> SBCL 1.0.2 (on Fedora Core 6 x86-64, from the extras repository)
> * (case 'quote ('lambda 1) (otherwise 2))
> [...]
> 1
>
> CLisp 2.41 (as above):
> [1]> (case 'quote ('lambda 1) (otherwise 2))
> 1
>
> Both implementations give less surprising results for (eq 'quote
> 'lambda) and (case 'lambda ('quote 1) (otherwise 2)).
>
> Is this the correct behavior (and if so, where should I look in the
> Hyperspec to understand it)?  Or do these independent implementations
> share an obscure bug?

    I think that the correct behavior, and should evaluate to 1 on all 
Common Lisp systems.  "case" doesn't evaluate its "key" arguments.  So 
'lambda is the same as the two element list (quote lambda).  Compare 
to...

(case 'quote
    ((lambda quote) 1)
    (otherwise 2))

...which also evaluates to 1.  You might also want to study these 
examples...

(case 'foo
      ((foo bar baz) 1)
      (otherwise 2))

(case 'bar
      ((foo bar baz) 1)
      (otherwise 2))
From: David Wragg
Subject: Re: (case 'quote ('lambda 1) (otherwise 2))
Date: 
Message-ID: <1170112766.274652.258130@s48g2000cws.googlegroups.com>
On Jan 29, 10:26 pm, "Greg Buchholz" <················@yahoo.com> 
wrote:
> "case" doesn't evaluate its "key" arguments.

Ah, I see.  Thanks.  At some point I forgot that.  And because my keys 
always looked like 'symbol, I didn't notice this until now!

And thanks to Pascal for the advice to always put the keys in a list.  
I will bear that in mind also.
From: Greg Buchholz
Subject: Re: (case 'quote ('lambda 1) (otherwise 2))
Date: 
Message-ID: <1170109830.521596.311270@k78g2000cwa.googlegroups.com>
David Wragg wrote:
> I have found 2 Common Lisp implementations that think that the above
> code evaluates to 1.  This is quite surprising to me.

    You probably meant to say...

    (case 'quote (lambda 1) (otherwise 2))

...to compare the symbol "quote" to the symbol "lambda".

Greg Buchholz
From: Pascal Bourguignon
Subject: Re: (case 'quote ('lambda 1) (otherwise 2))
Date: 
Message-ID: <873b5to301.fsf@thalassa.informatimago.com>
"David Wragg" <·····@wragg.org> writes:

> I have found 2 Common Lisp implementations that think that the above 
> code evaluates to 1.  This is quite surprising to me.
>
> SBCL 1.0.2 (on Fedora Core 6 x86-64, from the extras repository)
> * (case 'quote ('lambda 1) (otherwise 2))
> [...]
> 1
>
> CLisp 2.41 (as above):
> [1]> (case 'quote ('lambda 1) (otherwise 2))
> 1
>
> Both implementations give less surprising results for (eq 'quote 
> 'lambda) and (case 'lambda ('quote 1) (otherwise 2)).
>
> Is this the correct behavior (and if so, where should I look in the 
> Hyperspec to understand it)?  Or do these independent implementations 
> share an obscure bug?

Yes, you will find that all conforming implementations will return 1 here.

You have to remember that ' is a reader macro which expands to a list:
(read-from-string "'x") --> (QUOTE X)

[and #' is a dispatching reader macro that expands similarly to a
list, but with FUNCTION instead of QUOTE:

(read-from-string "#'x") --> (FUNCTION X)
]

Now, when you try these read-from-string forms, you must be careful
not to be misled by your implementation printer, which usually process
specially lists such as (QUOTE X) and (FUNCTION X) and print them as
'X and #'X instead of printing them as normal lists.  To be sure, you
can use your own list printing function:

(defun print-list (list &optional (stream *standard-output*))
  (princ "(")
  (when list
    (loop
       :for head = list :then (cdr head)
       :while (cdr head)
       :do (prin1 (car head)) (princ " ")
       :finally (prin1 (car head))))
  (princ ")")
  list)


C/USER[46]> (print-list '(quote x))
(QUOTE X)
'X
C/USER[47]> (print-list '(function x))
(FUNCTION X)
#'X


So your form: (case 'quote ('lambda 1) (otherwise 2))
is read as:   (case (quote quote) ((quote lambda) 1) (otherwise 2))

Now, the point is that CASE doesn't evaluates the keys listed in
normal-clause.   The keys you gave in your first clause is (QUOTE
LAMBDA), which is a list of two keys, QUOTE and LAMBDA.  It happens
that the evaluation of (QUOTE QUOTE) returns QUOTE, which is exactly
the first key in the the list of keys of the first clause.

My advice with CASE is to always write the keys in a list, even if you
have only one key:

(case (quote quote)
  ((lambda)  1)
  (otherwise 2))
--> 2


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Nobody can fix the economy.  Nobody can be trusted with their finger
on the button.  Nobody's perfect.  VOTE FOR NOBODY.
From: ············@googlemail.com
Subject: Re: (case 'quote ('lambda 1) (otherwise 2))
Date: 
Message-ID: <1170135855.271233.54700@v45g2000cwv.googlegroups.com>
On Jan 29, 11:57 pm, Pascal Bourguignon <····@informatimago.com> 
wrote:
> Now, when you try these read-from-string forms, you must be careful
> not to be misled by your implementation printer, which usually process
> specially lists such as (QUOTE X) and (FUNCTION X) and print them as
> 'X and #'X instead of printing them as normal lists.  To be sure, you
> can use your own list printing function:

Hmm, maybe I should use something similar when I want things to pretty-
print like (function ...) rather than #'.... (Say, in a quick 'n dirty 
logfile thing, where #'... did once annoy me.)


;; Bind this to nil if you want sourcecode to be printed using a style 
like
;; (function ...) rather than #'...
(defvar *print-code-fancily* t)

(defun length-2? (x) (= 2 (length x)))

;; Installs pretty-print dispatchers for FUNCTION and QUOTE forms.
(flet ((set-pprint-dispatch... (type original-dispatcher)
         (set-pprint-dispatch
          ` (and (cons (eql ,type))
                 (satisfies length-2?))
          (lambda (s list)
            (if *print-code-fancily*
                (funcall original-dispatcher s list)
                (funcall (formatter "~:<~W ~_~W~:>") s list))))))
  (set-pprint-dispatch... 'function
                          (pprint-dispatch '(function x)
                                           (copy-pprint-dispatch 
nil)))
  (set-pprint-dispatch... 'quote
                          (pprint-dispatch '(quote x)
                                           (copy-pprint-dispatch 
nil))))


Keep in mind I've almost never messed with the pretty-printer before..


Tayssir
--

Anarchism and the Academy:
http://mbanna.radio4all.net/pub/archive5/mp3_4/200108-renew-acad-p.mp3
http://mbanna.radio4all.net/pub/archive5/mp3_4/200108-renew-acad-q.mp3
From: ············@googlemail.com
Subject: Re: (case 'quote ('lambda 1) (otherwise 2))
Date: 
Message-ID: <1170183034.577830.69900@p10g2000cwp.googlegroups.com>
On Jan 30, 6:44 am, ············@googlemail.com wrote:
> Hmm, maybe I should use something similar when I want things to pretty-
> print like (function ...) rather than #'.... (Say, in a quick 'n dirty
> logfile thing, where #'... did once annoy me.)
>
> ;; Bind this to nil if you want sourcecode to be printed using a style
> ;; like (function ...) rather than #'...
> (defvar *print-code-fancily* t)
> [...]

Oh, speaking of depressingly hackish code, there's a new defmacro.org 
article out, which consoled me a bit about it...
<http://www.defmacro.org/ramblings/lisp-ducati.html>

(Apparently defmacro.org isn't on Planet Lisp.)


Tayssir
From: Tim Bradshaw
Subject: Re: (case 'quote ('lambda 1) (otherwise 2))
Date: 
Message-ID: <1170149678.593905.314520@h3g2000cwc.googlegroups.com>
On Jan 29, 9:48 pm, "David Wragg" <····@wragg.org> wrote:
> I have found 2 Common Lisp implementations that think that the above
> code evaluates to 1.  This is quite surprising to me.

It should not be.  If expand the syntactic sugar what you have is

(case (quote quote) ((quote lambda) 1) (otherwise 2))

and I think it's now clear what the answer is: because QUOTE is EQL to 
QUOTE, so the first clause matches.  The mistake you've made is to 
assume that the keys in a CASE clause are evaluated and therefore need 
quoted: they're not (and in fact, you've not been quite consistent, 
since you didn't quote OTHERWISE...).

--tim
From: robert maas, see http://tinyurl.com/uh3t
Subject: Re: (case 'quote ('lambda 1) (otherwise 2))
Date: 
Message-ID: <rem-2007jan31-002@yahoo.com>
> From: "David Wragg" <····@wragg.org>
> I have found 2 Common Lisp implementations that think that the above
> code evaluates to 1.  This is quite surprising to me.

Why should you be surprised? That's what it's supposed to do.
You do know that ' is a reader macro, which takes effect at the
time the expression is parsed from the input stream?
So by the time eval sees what you typed, it's actually:
(case (quote quote) ((quote lambda) 1) (otherwise 2))
Now look up documentation for case:
<http://www.lispworks.com/documentation/HyperSpec/Body/m_case_.htm>
   case keyform {normal-clause}* [otherwise-clause] => result*
   keyform---a form; evaluated to produce a test-key.
So (quote quote) is evaluated to produce the symbol quote.
   normal-clause::= (keys form*)
So keys is (quote lambda) in your example.
   keys---a designator for a list of objects. In the case of case, the
   symbols t and otherwise may not be used as the keys designator. To
   refer to these symbols by themselves as keys, the designators (t) and
   (otherwise), respectively, must be used instead.
Think carefully, does it say anything about keys being a form that
gets evaluated? How could (t) or (otherwise) work if it were
evaluated?? It's not evaluated. You get a list of two keys, the key
quote, and the key lambda, either of which will match if you give
the appropriate test-key.

So you gave the test-key quote, which matches the key quote, voila.

Somebody else suggested always making a list of keys, even if
you're matching for just a single key. I like that idea, because
then you don't have to keep in mind that t and otherwise have
special meanings when used alone outside a list.

I also suggest not to use apostrophe (reader macro) if using it
confuses you about what you're really feeding into lisp.

I do have one fault with the meta-spec: It doesn't say that except
for t and otherwise you can write a single object without putting
it in a list. It hints at that, but doesn't say clearly.

> Both implementations give less surprising results for
> (eq 'quote 'lambda) and (case 'lambda ('quote 1) (otherwise 2)).

eq evaluates both arguments.

In that last case example, you're actually searching for the key
quote, or the key quote. That's right, you have two copies of the
same key there, either of which will match when the test key is
quote. For example:
(case 'quote ('quote 1) (otherwise 2)) --> 1
but probably not for the reason you thought!

> where should I look in the Hyperspec to understand it)?

Go to the index page, where you'll see:
CASE
  Macro CASE, CCASE, ECASE
Click on that to get to the page I was quoting from.
Note that because it's a macro, you might try:
(macroexpand '(case 'quote ('lambda 1) (otherwise 2)))
(LET ((#:G862 'QUOTE))
  #:G862
  (COND ((OR (EQL #:G862 'QUOTE) (EQL #:G862 'LAMBDA)) NIL 1) (T NIL 2)))
Does the (OR (EQL #:G862 'QUOTE) (EQL #:G862 'LAMBDA)) part give a
clue as to the semantics?