Path: g2news1.google.com!news3.google.com!feeder1-2.proxad.net!proxad.net!feeder1-1.proxad.net!cleanfeed3-a.proxad.net!nnrp17-1.free.fr!not-for-mail Newsgroups: comp.lang.lisp Subject: Re: Bidirectional streams Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAQMAAABtzGvEAAAABlBMVEUAAAD///+l2Z/dAAAA oElEQVR4nK3OsRHCMAwF0O8YQufUNIQRGIAja9CxSA55AxZgFO4coMgYrEDDQZWPIlNAjwq9 033pbOBPtbXuB6PKNBn5gZkhGa86Z4x2wE67O+06WxGD/HCOGR0deY3f9Ijwwt7rNGNf6Oac l/GuZTF1wFGKiYYHKSFAkjIo1b6sCYS1sVmFhhhahKQssRjRT90ITWUk6vvK3RsPGs+M1RuR mV+hO/VvFAAAAABJRU5ErkJggg== X-Accept-Language: fr, es, en X-Disabled: X-No-Archive: no References: From: p...@informatimago.com (Pascal J. Bourguignon) Date: Thu, 01 Jan 2009 13:43:54 +0100 Message-ID: <87d4f7kxh1.fsf@informatimago.com> Organization: Informatimago User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.3 (darwin) Cancel-Lock: sha1:ZGE1YzZkZTMzNjk2NTUwYjI4MmYzNzU3ZjBkZmJhMTBlMmM5NDMyNw== MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Lines: 83 NNTP-Posting-Date: 01 Jan 2009 13:43:55 MET NNTP-Posting-Host: 88.182.134.169 X-Trace: 1230813835 news-1.free.fr 18449 88.182.134.169:52550 X-Complaints-To: abuse@proxad.net Juanjo writes: > Given the following piece of code, which behavior do you find more > correct of the ones shown below? > > (with-open-file (s "foo.txt" :direction :io :if-exists :supersede) > (write-line (print "abcdefghijk") s) > (file-position s 0) > (let (a) > (print (list (file-position s) > (setf a (read-char s)) > (file-position s) > (unread-char a s) > (file-position s) > (write-char #\x s) > (file-position s) > (read-char s) > (file-position s) > (read-char s)))) > (file-position s 0) > (print (read-line s))) > > Basically the problem relates to the value of file-position and the > actual place where data is written right after an unread-char > operation. This behavior also affects the behavior of an > implementation when reading, for instance, a Return + Linefeed > sequence. > > Is this simply undefined? I found the section on streams in the ANSI > specification to be, say, lacking in all aspects, hehe. > > This is SBCL 1.0.10, an implementation of ANSI Common Lisp. > "abcdefghijk" > (0 #\a 1 NIL 0 #\x 1 #\a 2 #\b) > "abxdefghijk" > > ECL (Embeddable Common-Lisp) 8.12.0 (CVS 2008-07-12 18:54) > "abcdefghijk" > (0 #\a 1 NIL 1 #\x 2 #\a 2 #\c) > "axcdefghijk" > > Welcome to GNU CLISP 2.45 (2008-04-04) > "abcdefghijk" > (0 #\a 1 NIL 0 #\x 1 #\a 2 #\c) > "axcdefghijk" Well, the note of UNREAD-CHAR says that it's just a Q&D hack to let the lisp reader look ahead one character. The lisp reader doesn't write the stream it reads, and doesn't use file-position since it will work on streams with no attached file. So clearly, when mixin file-position and write-char with unread-char, you're out of bounds of unread-char. This is simply undefined, and anything goes. Personnaly, I would have a preference for this result: (0 #\a 1 nil 0 #\x 1 #\b 2 #\c) "xbcdefghijk" But note that when you mix read-char, write-char, and file-position (implicitly thru unread-char) on streams encoded in UTF-8 (or some other variable width character encoding), you may get very surprizing results. What if the stream contained "áeìoü"? File positions after reading each character may be: 0 2 3 5 6 8, or you could even have bigger increments with normalized forms. So unreading a character, it may be difficult to find the correct file position. And then, writting over a character that needs a different number of bytes should prevent further reading characters. So your code is really nasty, you can't complain for the implementation variability. -- __Pascal Bourguignon__