我正在阅读Practical Common Lisp这本书,并且有一段代码,我正在使用Clozure CL实现:
(defun prompt-read (prompt)
(format *query-io* "~a:" prompt)
(force-output *query-io*)
(read-line *query-io*))
成功定义函数后,我通过
调用它(prompt-read "Hello")
然后输入"你好"并按下回车键,输出如下:
CL-USER> (prompt-read "Hello")
Hello:hello
"hello"
NIL
添加了一个额外的空白行,我尝试了下面的代码,没有其他新行:
(defun test-read ()
(read-line *query-io*))
然后执行它,结果如下:
CL-USER> (test-read)
hello
"hello"
NIL
这次没有产生额外的空白行,实际上我发现每次读取行都遵循格式函数时,会产生一个空白行。我尝试了Clisp实现中的代码,两种情况都没有产生空白行,我只是想知道为什么出现空行,另一个问题是read-line返回两个值吗?因为我在每次输入的字符串后面看到NIL,这个NIL是什么意思?
感谢您的帮助!
答案 0 :(得分:4)
这是Clozure CL与SLIME read-eval-print-loop(REPL)的交互。原生的Clozure CL REPL不会这样做。
; SLIME 2014-05-16
CL-USER> (defun prompt-read (prompt)
(format *query-io* "~a:" prompt)
(force-output *query-io*)
(read-line *query-io*))
PROMPT-READ
CL-USER> (prompt-read "Hello")
Hello:hello
"hello"
NIL
如果你多次调用它,那么你会看到你的代码没有添加换行符,但是当输出完成时,REPL会在输出和返回的值之间输出一行。
CL-USER> (progn (prompt-read "Hello")
(prompt-read "Hello")
(prompt-read "Hello"))
Hello:hello
Hello:hello
Hello:hello
"hello"
NIL
每个Lisp实现都有一些SLIME后端的特殊代码。也许有区别。
答案 1 :(得分:1)
当我在SBCL中尝试类似的代码时,我没有得到您描述的输出(参见附录)。你没有提到你正在使用的实现方法,但我希望REPL输出一个新行,可以直接使用 fresh-line 函数,也可以使用tilde-ampersand format指令。请注意文档中有关 fresh-line (强调添加)的内容:
fresh-line类似于terpri,但仅在输出时才输出换行符 输出流尚未出现在行的开头。 如果对某些人来说 无法确定的原因,无论如何都会输出换行符。 如果输出换行符,则换行符返回true;否则它会返回 假的。
如果您使用(格式* query-io * ...)显示的提示将系统置于“无法确定”的状态,那么根本不会让我感到惊讶,因此,您将获得您所看到的“额外”换行符。如果您将格式指令更改为“~a:〜%”,您会得到相同的行为吗?
另一个问题是read-line返回两个值吗?因为我 在每次输入的字符串后面看到NIL,这个NIL是什么 意思?
作为Barmar pointed out in the comments,文档清楚地指出读取行返回两个值,第二个指示输入是由换行符还是文件结尾终止。
read-line&可选输入流eof-error-p eof-value recursive-p
⇒行,缺少 - 换行符-p...次要值,missing-newline-p,是一个通用布尔值,如果换行符被换行,则为false;如果换行符的文件末尾终止行,则为true;如果是line是eof-value)。
* (defun prompt-read (x)
(format *query-io* "~a:" x)
(force-output *query-io*)
(read-line *query-io*))
PROMPT-READ
* (prompt-read "Hello")
Hello:hello
"hello"
NIL
* (defun test-read ()
(read-line *query-io*))
TEST-READ
* (test-read)
hello
"hello"
NIL