From: Matt K. <kau...@cs...> - 2011-10-18 23:08:46
|
Hi -- Consider the following simple reader extension: (defun sharp-bang-read (stream char n) (declare (ignore char n)) (read stream) (read stream)) (set-dispatch-macro-character #\# #\! #'sharp-bang-read) Now suppose I issue the following: #! 3 4 I'd expect the reader to read 4, and it does. But with SBCL, I don't get the prompt back until I hit <return>. (I used SBCL 1.0.51 on a Mac and SBCL 1.0.49 on Linux.) I tried Allegro CL, CCL, CLISP, GCL, and Lispworks, and didn't have this problem with those Lisps. I did however have this problem with CMUCL, perhaps not surprisingly given SBCL's heritage (as I understand it). Is this an SBCL bug, or am I doing something wrong? Below is a sequence of inputs followed by a corresponding log, in case it's helpful. In the log, I've inserted <return> to show where I had to hit that key to get back to the top-level prompt. ============================== (defun sharp-bang-read (stream char n) (declare (ignore char n)) (read stream) (read stream)) (set-dispatch-macro-character #\# #\! #'sharp-bang-read) #! 3 4 (trace sharp-bang-read) (set-dispatch-macro-character #\# #\! #'sharp-bang-read) #! 3 4 (untrace) (defun sharp-bang-read (stream char n) (declare (ignore char n)) (read stream) (read stream) (format t "Finished the read~%") (finish-output) (force-output)) (set-dispatch-macro-character #\# #\! #'sharp-bang-read) #! 3 4 ============================== Here is a log. As mentioned above, I've inserted <return> below where I actually had to hit a <return> in order to get back to the top-level prompt. ~$ sbcl This is SBCL 1.0.51.0-a546163, an implementation of ANSI Common Lisp. More information about SBCL is available at <http://www.sbcl.org/>. SBCL is free software, provided as is, with absolutely no warranty. It is mostly in the public domain; some portions are provided under BSD-style licenses. See the CREDITS and COPYING files in the distribution for more information. * (defun sharp-bang-read (stream char n) (declare (ignore char n)) (read stream) (read stream)) SHARP-BANG-READ * (set-dispatch-macro-character #\# #\! #'sharp-bang-read) T * #! 3 4 <return> 4 * (trace sharp-bang-read) (SHARP-BANG-READ) * (set-dispatch-macro-character #\# #\! #'sharp-bang-read) T * #! 3 4 0: (SHARP-BANG-READ #<SYNONYM-STREAM :SYMBOL SB-SYS:*STDIN* {100E6761}> #\! NIL) 0: SHARP-BANG-READ returned 4 <return> 4 * (untrace) T * (defun sharp-bang-read (stream char n) (declare (ignore char n)) (read stream) (read stream) (format t "Finished the read~%") (finish-output) (force-output)) STYLE-WARNING: redefining COMMON-LISP-USER::SHARP-BANG-READ in DEFUN SHARP-BANG-READ * (set-dispatch-macro-character #\# #\! #'sharp-bang-read) T * #! 3 4 Finished the read <return> NIL * ============================== Thanks for your time. Regards, Matt Kaufmann |
From: Stig H. <sti...@gm...> - 2011-10-18 23:39:26
|
The problem is that the last (READ STREAM) reads the following newline and discards it. The REPL then needs another newline to end the line. This is in fact according to spec, here is what the description of READ says: When *read-suppress* is false, read throws away the delimiting character required by certain printed representations if it is a whitespace[2] character; but read preserves the character (using unread-char) if it is syntactically meaningful, because it could be the start of the next expression. You can use READ-PRESERVING-WHITESPACE instead to get the effect you want. Stig Hemmer |
From: Matt K. <kau...@cs...> - 2011-10-19 00:01:50
|
Thank you for the quick reply! That solves my problem. Actually, your reply led me to read the spec more carefully, and I realized that since I'm calling read recursively, I should probably use recursive-p = t, thus: (defun sharp-bang-read (stream char n) (declare (ignore char n)) (read stream t nil t) (read stream t nil t)) That solves the problem, too; I'll probably go with this unless I hear that it's not a good idea. Regards, and thanks again, Matt DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=xcoQgmorEd54v46wec6y8N9Oet7ACI8+R8FCKE3IoEg=; b=SY03NE/ZsmZlTT9YJeBtFjCnC8Zjqllv4IYVsh+KtIpD+B+JReUr9/63clezFXVj0O JMmlUGyxuQ0+k+YUvVoIEJMtS5hebu1Ur55bNp97VBBhCqFJdt7ddlQluOF9D8H46SGw jiovfxh/ZtC7M1o0tpqICNTUl/mukca1H+T5s= MIME-Version: 1.0 Date: Wed, 19 Oct 2011 01:39:19 +0200 From: Stig Hemmer <sti...@gm...> Cc: sbc...@li... Content-Type: text/plain; charset=ISO-8859-1 The problem is that the last (READ STREAM) reads the following newline and discards it. The REPL then needs another newline to end the line. This is in fact according to spec, here is what the description of READ says: When *read-suppress* is false, read throws away the delimiting character required by certain printed representations if it is a whitespace[2] character; but read preserves the character (using unread-char) if it is syntactically meaningful, because it could be the start of the next expression. You can use READ-PRESERVING-WHITESPACE instead to get the effect you want. Stig Hemmer |