UNREAD-CHAR-AFTER-PEEK-CHARPEEK-CHAR and UNREAD-CHAR are very similar mechanisms. The description of PEEK-CHAR in CLtL even states that "it is as if one had called READ-CHAR and then UNREAD-CHAR in succession." But while CLtL prohibits calling UNREAD-CHAR twice in succession it does not prohibit calling UNREAD-CHAR after PEEK-CHAR. The obvious implementation of PEEK-CHAR and UNREAD-CHAR (a one-character buffer) will not work unless this prohibition is present.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 specified.
In particular, the results of calling UNREAD-CHAR after PEEK-CHAR is unspecified.
This is not legal, since the PEEK-CHAR for char2a "commits" the character read by char1a, and so the unread-char is not legal.
PEEK-CHAR and UNREAD-CHAR provide equivalent functionality and it is thus reasonable for an implementation to implement them in terms of the same mechanism.TCP/FTP) handled this correctly, while another did not.
In Symbolics Genera, for the Example above:
(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.
PEEK-CHAR or UNREAD-CHAR, but not both.UNREAD-CHAR and PEEK-CHAR work, rather than two separate one-char buffers.