[英]sbcl (and clisp): When is a character not a character? (using defconstant)
这个问题是关于sbcl的。 问题:什么时候字符不是字符? 考虑以下代码:
(defconstant +asc-lf+ #\Newline)
(defconstant +asc-space+ #\Space)
(prin1 (type-of #\Newline )) (terpri)
(prin1 (type-of #\Space )) (terpri)
(prin1 (type-of +asc-lf+ )) (terpri)
(prin1 (type-of +asc-space+)) (terpri)
如预期的那样,它将产生:
STANDARD-CHAR
STANDARD-CHAR
STANDARD-CHAR
STANDARD-CHAR
现在考虑以下代码:
(defun st (the-string)
(string-trim '(#\Newline #\Space) the-string))
(princ "\"")
(princ (st " abcdefgh "))
(princ "\"")
(terpri)
它产生:
"abcdefgh"
但是请考虑以下代码:
(defconstant +asc-lf+ #\Newline)
(defconstant +asc-space+ #\Space)
(defun st (the-string)
(string-trim '(+asc-lf+ +asc-space+) the-string))
(princ "\"")
(princ (st " abcdefgh "))
(princ "\"")
(terpri)
使用sbcl加载时,它会为您提供:
While evaluating the form starting at line 6, column 0
of #P"/u/home/sbcl/experiments/type-conflict.d/2.lisp":"
debugger invoked on a TYPE-ERROR:
The value
+ASC-LF+
is not of type
CHARACTER
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [RETRY ] Retry EVAL of current toplevel form.
1: [CONTINUE] Ignore error and continue loading file "/u/home/sbcl/experiments/type-conflict.d/2.lisp".
2: [ABORT ] Abort loading file "/u/home/sbcl/experiments/type-conflict.d/2.lisp".
3: Exit debugger, returning to top level.
((FLET SB-IMPL::TRIM-CHAR-P :IN SB-IMPL::GENERIC-STRING-TRIM) #\ )
0]
最初,我期望能够报告clisp对预期的返回值或可能的错误进行了对#'string-trim
的适当调用。 但这都不是。 该函数返回传递给它的相同字符串,而不进行任何修剪。
这是应该发生的事吗? 我想念什么?
编辑约 2017-10-21 08:50 UTC
PuercoPop的出色回答激发了后续问题。 如果我将其作为一个单独的问题发布,只需给出一个词,我会的。
为什么会这样(至少使用sbcl和clisp):
(defconstant +asc-lf+ #\Newline)
(defconstant +asc-space+ #\Space)
(prin1 (type-of (first (list #\Newline #\Space))))
(terpri)
(prin1 (type-of (first '(#\Newline #\Space))))
(terpri)
产生这个吗?
STANDARD-CHAR
STANDARD-CHAR
有了PuercoPop的回答,我希望它会为第二个表达式产生一些有关符号而不是字符的信息。
主要的困惑来自
(+ ab)
是代码,这里是一个函数调用。 (quote (+ ab))
和'(+ ab)
都是数据,因为它们对引用的文字数据进行求值。 #\\newline
已作为字符对象读取。 它是内置语法: Sharpsign Backslash它不是字符串,不是符号,也不是一些未知的数据。 它被读取为character类型的对象 (我在这里使用的是word 字符对象 ,也可以只说出character )。 这些是符号:
foo
bar
+foo+
*the-foo*
当符号得到评估时,它们便会评估其价值。
这些是角色对象:
#\f
#\O
#\o
#\newline
当字符对象得到评估时,它们将对自己进行评估。 因此, '#\\foo
, (quote #\\foo)
和#\\foo
对所有对象求值。
这些是清单
(newline #\newline) ; the first item is a symbol, the second a character object
(#\a #\b #\c) ; a list of character objects
(a b c) ; a list of symbols
如果我们评估列表会发生什么:
(+ a b) ; the sum of the values of A and B
(list a b) ; a list gets computed, with the values of variables a and b
(list 'a 'b) ; a list gets computed, with the symbols A and B
'(a b) ; a literal list of the symbols A and B
'(#\a #\b) ; a literal list of the character objects #\a and #\b
'(a #\a) ; a literal list of the symbol A and the character object #\a
(#\a #\b) ; an error, #\a is not a function/macro/special-form
(+ a 'b) ; an error, a symbol B is not a number
评估加引号的列表:
`(a ,a #\a ,#\a) ; a list of the symbol a, the value of the variable a,
; the character object a and again the character object a
您的错误 :
'(+asc-lf+ +asc-space+)
得出一个符号列表。
函数STRING-TRIM
需要一个字符序列。
您需要编写如下内容:
(list +asc-lf+ +asc-space+) ; calling the function list
`(,+asc-lf+ ,+asc-space+) ; a backquoted list with comma for evaluation
(vector +asc-lf+ +asc-space+) ; the constructed vector is also a sequence
也:
(list #\\Newline #\\Space)
和'(#\\Newline #\\Space)
评估为一个字符列表。 #\\
语法是Lisp 阅读器的内置功能,用于构造字符对象。 因此, #\\newline
在读取时被转换为字符对象:
CL-USER 82 > (describe (read))
#\Newline ; we type the nine characters #\Newline
#\Newline is a CHARACTER
Name "Newline"
Code 10
问题是您引用了“字符列表”。 因此,不是字符列表,而是符号列表。 那是
(defun st (the-string)
(string-trim (list +asc-lf+ +asc-space+) the-string))
错误消息提示说
值+ ASC-LF +不是CHARACTER类型的
并不是
值#\\ Newline的类型不是CHARACTER
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.