Read-byte, case and char-code


#1

Please excuse me for bothering you with boring little things, but I have a strange behavior with the uLisp ARM 3.3a version running on a Serpente device:

This code snippet is to make sure that only 1 or 0 is entered:

(defun input-test ()
    (let* (input_key)
      (loop
        (format t "~%Input [0/1]? ")
        (setq input_key (read-byte))
        (format t "  = ~a" input_key)
        (case input_key
          (((char-code #\0) (char-code #\1)) (return))
          (50 (return))
        )
      )
      (format t "~%~%OK - Input was: ~a" input_key)
    )
)

but the command (char-code #\0) seems not to be processed the right way…
This is what the output looks like:

2997> (input-test)

Input [0/1]? 0  = 48
Input [0/1]? 1  = 49
Input [0/1]? 2  = 50

OK - Input was: 50
nil

only the number 2 (code: 50) works.
I also tested this line of code:

((#\0 #\1) (return))

Without success…
But I think it should work like this, because the code corresponds to the example in “Lisp for C programmers”.

Only this one works:

((48 49) (return))

Thanks for your help
Hans-Günther


#2

The reason your first version doesn’t work is that case doesn’t evaluate the keys - they should be constants. You can make your version work by changing the case to:

(case input_key
  ((#.(char-code #\0) #.(char-code #\1)) (return))
  (50 (return)))

which evaluates them at read time. For a full explanation see:

Alternatively you could change it to a cond, which does evaluate the tests:

(cond
 ((or (= input_key (char-code #\0)) (= input_key (char-code #\1))) (return))
 ((= input_key 50) (return)))

Your second version:

((#\0 #\1) (return))

doesn’t work because input_key contains the integer ASCII code of the key, but #\0 and #\1 are characters, so they don’t match. You could fix that by changing it to:

(case (code-char input_key)
  ((#\0 #\1) (return))
  (#\2 (return)))

David


#3

Hello David,
thank you for the quick and detailed answer. This is very valuable.
The explanation makes sense and (cond …) makes the code more elegant, but then perhaps it would be good to update the code example in the chapter “Lisp for C programmers”?
Hans-Günther


#4

Ah - I see what you mean. It should be:

(setq key (code-char (read-byte)))
(case key
  (#\C (clear-screen))
  (#\I (invert-screen))
  ((#\R #\F) (rotate-screen))
  (t (print "Key not recognised")))

#5

Yeah, right. I was puzzled, because according to the example it should have worked.

And thank’s again for the detailed explanation…

Hans-Günther


#6