[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Issue: UNREAD-CHAR-AFTER-PEEK-CHAR (Version 1)



This is a reasonable issue. I think I'll eventually buy into it, but let
me suggest some changes I'd like to see before I do.

 - The proposal part is confusingly worded.

   The wording says that in a stream "abc", if I READ-CHAR to get the #\a
   into variable CH1 and then I PEEK-CHAR to see the "b", then I must call
   READ-CHAR before I can (UNREAD-CHAR CH1). But if I take that literally,
   I'll do (SETQ CH2 (READ-CHAR S)) (UNREAD-CHAR CH1 S) and that's not what
   I want. Having done the READ-CHAR, I can only UNREAD-CHAR the char I just
   did READ-CHAR to get. In effect, I can never UNREAD-CHAR CH1 once I've
   peeked at or read the next char. Some streams will let me back up at this
   point, but only those which would have let me back up before doing the
   READ-CHAR in the first place.

   It would be clearer for the proposal to just say that doing either a
   PEEK-CHAR or READ-CHAR `commits' all previous characters. UNREAD-CHAR
   on any character preceding that which is seen by the PEEK-CHAR (including
   those passed over by PEEK-CHAR when `seeking' with a non-NIL first
   argument) is not portable.

 - A misreading of the proposal might lead one to believe that one could
   do (SETQ CH1 (READ-CHAR STREAM))
      (SETQ CH2 (PEEK-CHAR NIL STREAM))
      (SETQ CH3 (READ-CHAR STREAM))
      (UNREAD-CHAR CH1 STREAM)
   since the unread-char is correctly separated from the PEEK-CHAR by an
   intervening READ-CHAR. The problem is that the wrong char is being
   unread. Some implementations support this, but it's definitely not
   condoned by the description of UNREAD-CHAR on p379.

 - I found the following test case to be more insightful:

   (defun test (&optional (stream *standard-input*))
     (let* ((char1a (read-char stream))
	    (char2a (peek-char nil stream))
	    (char1b (progn (unread-char char1a stream)
			   (read-char stream)))
	    (char2b (read-char stream)))
       (list char1a char2a char1b char2b)))

  - Current practice (for my test case above) in Symbolics Genera:

     (test)ab
     => (#\a #\b #\a #\b)

     (with-input-from-string (s "abc") (test s))
     => (#\a #\b #\a #\b)

     (progn (with-open-file (s "foo.output" :direction :output)
	      (write-string "abc" s))
            (with-open-file (s "foo.output" :direction :input) 
	      (test s)))
     Signals an error about unreading #\a when #\b was already unread.