开始一个新的 REPL,然后尝试检查每个步骤的返回值:
T1> (read)
foo
FOO
T1> (read)
1
1
T1> (type-of (read))
foo
SYMBOL
T1> (type-of (read))
1
BIT
现在请注意,STRING 不适用于所有输入类型:
T1> (string 'foo)
"FOO"
T1> (string 1)
还要注意,与setq 不同,(format foo ...) 不会设置 foo,但如果它是stream 或带有@987654323 的string,则写入它@。看看它的Documentation,你会看到:
格式化目标控制字符串
&rest args => 结果
[...]
destination---nil, t, a stream, or a
带有填充指针的字符串。
[...]
格式对于很好地制作很有用
格式化文本,产生好看的
消息等。格式可以
生成并返回字符串或输出
到目的地。
如果目的地是一个字符串,一个流,
或 t,则结果为零。
否则,结果为字符串
包含“输出”。
试试这样:
T1> (setq *answer*
(with-output-to-string (s)
(format s "~s" (read))))
1
"1"
T1> *answer*
"1"
或者像这样:
T1> (setq *answer* (make-array 20 :element-type 'character :fill-pointer 0))
""
T1> (format *answer* "~s" (read))
1
NIL
T1> *answer*
"1"
这些是我能在您的代码中找到的唯一相关错误。这肯定会在每个符合要求的 CL 中返回 "works"(您也可以使用 prin1-to-string):
T1> (defvar *answer*)
*ANSWER*
T1> (setq *answer* (format nil "~s" (read)))
1
"1"
T1> (if (stringp *answer*)
(princ "works")
(princ "failed"))
works
"works"
除非你在一个混乱的包中(在评估你的代码之前尝试(in-package cl-user)),或者重新定义基本功能,否则这将起作用。给出一些更准确的错误描述,如果还是不行的话。
ED:
读过比尔的回答,他正确指出 read-line 是一个更简短的解决方案,我应该提一下,我并没有试图在我的回答中展示最好、最简洁或最惯用的方法,而那些会取决于你真正想做的事情。 (最短的可能解决方案是"works" :) 它们只是有助于解释代码失败原因的示例。
我忘了说的另一件事是,您应该记住,除了涉足 REPL 之外,通常要避免在未使用 defvar 或 defparameter 定义的变量上的顶级 setqs,因为后果是不确定的。此外,按照惯例,这些变量用星号(也称为 earmuffs)包裹,以防止由于混淆特殊变量和词法范围变量而导致的错误。