普通的lisp调用read-line格式后在Clozure CL实现中产生一个额外的换行符

时间:2014-09-04 01:48:47

标签: lisp common-lisp

我正在阅读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是什么意思?

感谢您的帮助!

2 个答案:

答案 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)

空行可能来自FRESH-LINE

当我在SBCL中尝试类似的代码时,我没有得到您描述的输出(参见附录)。你没有提到你正在使用的实现方法,但我希望REPL输出一个新行,可以直接使用 fresh-line 函数,也可以使用tilde-ampersand format指令。请注意文档中有关 fresh-line (强调添加)的内容:

  

fresh-line类似于terpri,但仅在输出时才输出换行符   输出流尚未出现在行的开头。 如果对某些人来说   无法确定的原因,无论如何都会输出换行符。   如果输出换行符,则换行符返回true;否则它会返回   假的。

如果您使用(格式* query-io * ...)显示的提示将系统置于“无法确定”的状态,那么根本不会让我感到惊讶,因此,您将获得您所看到的“额外”换行符。如果您将格式指令更改为“~a:〜%”,您会得到相同的行为吗?

NIL

  

另一个问题是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)。

附录:SBCL成绩单

* (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