读取变量的正确输入
Read the proper input to a variable
我想要一个包含来自用户输入的 integer
的变量。它不能接受字符串,也不能接受十进制数。
我需要一些帮助来理解我在这里做错了什么。
到目前为止我的代码:
感谢您的帮助。
(format t "~%Enter a number: ")
(loop (defvar numb (read))
(cond (((rationalp numb)1)
(print "No decimal numbers are allowed, please enter an integer"))
(((stringp numb)1)
(print "No strings are allowed, please enter an integer"))
)
(when ((integerp numb)1) (return numb))
)
工作代码
以下是我的做法:
(defun ask-and-read (prompt)
"Prompt the user and read his input."
(princ prompt *query-io*)
(force-output *query-io*) ; flush the buffers
(let ((*read-eval* nil)) ; close the security hole
(read *query-io*)))
(defun request-object (prompt predicate)
"Ask the user for an object using prompt.
Only accept data which satisfies the predicate."
(loop
for object = (ask-and-read prompt)
when (funcall predicate object)
return object
do (format *query-io* "Alas, ~S (~S) does not satisfy ~S, please try again~%"
object (type-of object) predicate)))
示例:
> (request-object "Enter an integer: " #'integerp)
Enter an integer: 4.6
Alas, 4.6 (SINGLE-FLOAT) does not satisfy #<SYSTEM-FUNCTION INTEGERP>, please try again
Enter an integer: 5/7
Alas, 5/7 (RATIO) does not satisfy #<SYSTEM-FUNCTION INTEGERP>, please try again
Enter an integer: asdf
Alas, ASDF (SYMBOL) does not satisfy #<SYSTEM-FUNCTION INTEGERP>, please try again
Enter an integer: 7
==> 7
> (request-object "Enter a real: " #'realp)
Enter a real: 4.5
==> 4.5
> (request-object "Enter a real: " #'realp)
Enter a real: 5/8
==> 5/8
> (request-object "Enter a real: " #'realp)
Enter a real: "sdf"
Alas, "sdf" ((SIMPLE-BASE-STRING 3)) does not satisfy #<SYSTEM-FUNCTION REALP>, please try again
Enter a real: 8
==> 8
请参阅我使用的设施的文档:
你的错误
代码格式化
您的代码不可读,因为您的缩进不正确。
Lispers 不算括号——这是编译器和编辑器的工作。
我们看缩进。
请帮自己一个忙,使用 Emacs - 它会为你缩进代码,你会经常自己看到错误。
Defvar 是顶级形式
首先,defvar
是一种顶级形式,用于定义全局变量,而不是设置它们。
随后的调用 不会 更改值:
(defvar *abc* 1)
*abc*
==> 1
(defvar *abc* 10)
*abc*
==> 1 ; not 10!
使用setq
设置变量。
局部变量优先于全局变量
虽然 Lisp 确实允许全局变量,但主要的编程
Lisp 中的风格是函数式风格:每个函数都接收它的
"input" 数据作为参数,returns 其 "output" 数据作为值。
要实现函数式风格,更喜欢局部变量而不是全局变量。
您通过 let
或创建局部变量
let*
或者,在 loop
中,请参阅
Local Variable Initializations.
Cond 和 When 具有非常具体的语法
您的 cond
and when
表格中有额外的括号和 1
(?!)。
记住,parens are meaningful in Lisp。
安全第一!
绑定 *read-eval*
到 nil
在需要 read
之前
如果用户输入 #.(launch-nuclear-missiles)
,避免核 war
响应您的提示,因为通常 read
评估任何
在 #.
.
之后
我想要一个包含来自用户输入的 integer
的变量。它不能接受字符串,也不能接受十进制数。
我需要一些帮助来理解我在这里做错了什么。
到目前为止我的代码:
感谢您的帮助。
(format t "~%Enter a number: ")
(loop (defvar numb (read))
(cond (((rationalp numb)1)
(print "No decimal numbers are allowed, please enter an integer"))
(((stringp numb)1)
(print "No strings are allowed, please enter an integer"))
)
(when ((integerp numb)1) (return numb))
)
工作代码
以下是我的做法:
(defun ask-and-read (prompt)
"Prompt the user and read his input."
(princ prompt *query-io*)
(force-output *query-io*) ; flush the buffers
(let ((*read-eval* nil)) ; close the security hole
(read *query-io*)))
(defun request-object (prompt predicate)
"Ask the user for an object using prompt.
Only accept data which satisfies the predicate."
(loop
for object = (ask-and-read prompt)
when (funcall predicate object)
return object
do (format *query-io* "Alas, ~S (~S) does not satisfy ~S, please try again~%"
object (type-of object) predicate)))
示例:
> (request-object "Enter an integer: " #'integerp)
Enter an integer: 4.6
Alas, 4.6 (SINGLE-FLOAT) does not satisfy #<SYSTEM-FUNCTION INTEGERP>, please try again
Enter an integer: 5/7
Alas, 5/7 (RATIO) does not satisfy #<SYSTEM-FUNCTION INTEGERP>, please try again
Enter an integer: asdf
Alas, ASDF (SYMBOL) does not satisfy #<SYSTEM-FUNCTION INTEGERP>, please try again
Enter an integer: 7
==> 7
> (request-object "Enter a real: " #'realp)
Enter a real: 4.5
==> 4.5
> (request-object "Enter a real: " #'realp)
Enter a real: 5/8
==> 5/8
> (request-object "Enter a real: " #'realp)
Enter a real: "sdf"
Alas, "sdf" ((SIMPLE-BASE-STRING 3)) does not satisfy #<SYSTEM-FUNCTION REALP>, please try again
Enter a real: 8
==> 8
请参阅我使用的设施的文档:
你的错误
代码格式化
您的代码不可读,因为您的缩进不正确。 Lispers 不算括号——这是编译器和编辑器的工作。 我们看缩进。 请帮自己一个忙,使用 Emacs - 它会为你缩进代码,你会经常自己看到错误。
Defvar 是顶级形式
首先,defvar
是一种顶级形式,用于定义全局变量,而不是设置它们。
随后的调用 不会 更改值:
(defvar *abc* 1)
*abc*
==> 1
(defvar *abc* 10)
*abc*
==> 1 ; not 10!
使用setq
设置变量。
局部变量优先于全局变量
虽然 Lisp 确实允许全局变量,但主要的编程
Lisp 中的风格是函数式风格:每个函数都接收它的
"input" 数据作为参数,returns 其 "output" 数据作为值。
要实现函数式风格,更喜欢局部变量而不是全局变量。
您通过 let
或创建局部变量
let*
或者,在 loop
中,请参阅
Local Variable Initializations.
Cond 和 When 具有非常具体的语法
您的 cond
and when
表格中有额外的括号和 1
(?!)。
记住,parens are meaningful in Lisp。
安全第一!
绑定 *read-eval*
到 nil
在需要 read
之前
如果用户输入 #.(launch-nuclear-missiles)
,避免核 war
响应您的提示,因为通常 read
评估任何
在 #.
.