Lisp中的简单用户输入函数与复杂用户输入函数
在该站点:有如下用户输入功能:Lisp中的简单用户输入函数与复杂用户输入函数,lisp,common-lisp,Lisp,Common Lisp,在该站点:有如下用户输入功能: (defun prompt-read (prompt) (format *query-io* "~%~a: " prompt) (force-output *query-io*) (read-line *query-io*)) 与以下更简单的形式相比,上述功能是否有任何主要优势: (defun prompt-read2 (prompt) (format t "~%~a: " prompt) (setf answer (
(defun prompt-read (prompt)
(format *query-io* "~%~a: " prompt)
(force-output *query-io*)
(read-line *query-io*))
与以下更简单的形式相比,上述功能是否有任何主要优势:
(defun prompt-read2 (prompt)
(format t "~%~a: " prompt)
(setf answer (read-line)))
建议始终使用
强制输出
和*查询io*
吗?是的,您编写代码很简单,但第一个更清楚您在做什么:
*query io*是一个包含输入流的全局变量(您可以通过全局变量的*命名约定来判断)
连接到终端。提示读取的返回值将是
最后一个表单的值,即对READ-LINE的调用,它返回
读取的字符串(不带尾随换行符。)
这就是他们所说的*查询io*
关于可以放在那里的流,工作如下:
大多数其他I/O函数也接受T和NIL作为流指示符
但有不同的含义:作为流指示符,T表示
双向流*终端-IO*,而NIL指定
*标准输出*作为输出流,标准输入*作为输入流
在这种情况下,这似乎只是指向*标准输入*而不是双向流t设置这样的全局变量的答案是错误的。你只需返回答案,让来电者随心所欲。如果确实使用特殊(~global)变量,则应在名称周围加星号(
*ANSWER*
而不是ANSWER
)
FORCE-OUTPUT
需要确保用户在回答问题之前看到提示。如果我在终端中使用SBCL运行第二个版本,程序就会冻结,等待输入而不说任何话
*QUERY-IO*
应该用于从用户查询内容,因为某些环境可能希望以不同于其他输出的方式处理这些内容。例如,可能有人为您的程序编写GUI包装器,将查询转换为图形对话框。或者,他们可能希望将其作为脚本的一部分运行,提供来自字符串的输入
(defun prompt-read (prompt)
(format *query-io* "~%~a: " prompt)
(force-output *query-io*)
(read-line *query-io*))
(defun hello ()
(format t "~&Hello ~a!~%" (prompt-read "What's your name")))
(defmacro with-input ((input) &body body)
`(let ((*query-io* (make-two-way-stream (make-string-input-stream ,input)
(make-string-output-stream))))
,@body))
(defun test ()
(with-input ("jkiiski")
(hello))
(with-input ("rnso")
(hello)))
(test)
; Hello jkiiski!
; Hello rnso!
编辑
使用SBCLs灰色流的更复杂示例
(defclass foo-stream (sb-gray:fundamental-character-input-stream)
((output-input-script :initarg :script :accessor foo-stream-script)
(output-stream :initarg :out :accessor foo-stream-out)
(current-input :initform nil :accessor foo-stream-current-input)))
(defmethod sb-gray:stream-read-char ((stream foo-stream))
(with-accessors ((input foo-stream-current-input)
(out foo-stream-out)
(script foo-stream-script)) stream
(when (or (null input)
(not (listen input)))
(let ((output (string-trim '(#\space #\newline)
(get-output-stream-string out))))
(setf input (make-string-input-stream
(format nil "~a~%"
(cdr (assoc output script :test #'string=)))))))
(read-char input)))
(defun prompt-read (prompt)
(format *query-io* "~%~a: " prompt)
(force-output *query-io*)
(read-line *query-io*))
(defun hello ()
(format t "~&Hello ~a!~%" (prompt-read "What's your name"))
(format t "~&I'm ~a too!" (prompt-read "How are you"))
(format t "~&~a~%" (if (string-equal (prompt-read
"Do you want to delete all your files")
"yes")
"Deleting all files... (not really)"
"Not deleting anything.")))
(defmacro with-input-script ((script) &body body)
(let ((out-sym (gensym "out")))
`(let* ((,out-sym (make-string-output-stream))
(*query-io* (make-two-way-stream
(make-instance 'foo-stream
:out ,out-sym
:script ,script)
,out-sym)))
,@body)))
(defun test ()
(with-input-script ('(("What's your name:" . "jkiiski")
("How are you:" . "great")
("Do you want to delete all your files:" . "No")))
(hello))
(with-input-script ('(("What's your name:" . "Foo Bar")
("How are you:" . "fine")
("Do you want to delete all your files:" . "Yes")))
(hello)))
(test)
; Hello jkiiski!
; I'm great too!
; Not deleting anything.
; Hello Foo Bar!
; I'm fine too!
; Deleting all files... (not really)