sbcl(和clisp):什么时候角色不是角色?(使用def常量)

sbcl(和clisp):什么时候角色不是角色?(使用def常量),lisp,common-lisp,sbcl,clisp,Lisp,Common Lisp,Sbcl,Clisp,这个问题是关于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-o

这个问题是关于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
"abcdefgh"

现在考虑这个代码:

(defun st (the-string)
  (string-trim '(#\Newline #\Space) the-string))
(princ "\"")
(princ (st "   abcdefgh   "))
(princ "\"")
(terpri)
(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)
它产生:

STANDARD-CHAR
STANDARD-CHAR
STANDARD-CHAR
STANDARD-CHAR
"abcdefgh"

但请考虑此代码:

(defun st (the-string)
  (string-trim '(#\Newline #\Space) the-string))
(princ "\"")
(princ (st "   abcdefgh   "))
(princ "\"")
(terpri)
(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

普尔科普的完美回答引发了一个后续问题。如果我把这作为一个单独的问题发表,只要说出这个词,我会的

为什么至少在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的回答,我本以为它会为第二个表达式生成一个符号,而不是一个字符。

问题是您引用的是字符列表。因此,它不是一个字符列表,而是一个符号列表。就是

(defun st (the-string)
  (string-trim (list +asc-lf+ +asc-space+) the-string))
当错误消息显示

价值 +ASC-LF+不是类型 性格

而不是

价值 \换行符不是类型 性格


主要的困惑来自于

列表的双重用途:数据和代码。对于评估+AB是代码,这里是函数调用。引号+AB和“+AB”都是数据,因为它们的计算结果是引用的文字数据。 阅读已经创建了对象\换行符已作为字符对象读取。它是内置语法:它不是字符串,不是符号,也不是一些未知的数据。它被解读为字符类型的对象,我在这里使用字符对象的措辞,你也可以这样说。 这些是符号:

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

你出色的回答确实激发了后续问题的灵感,我在原始问题的末尾编辑了这个问题。如果我把它作为一个单独的问题发布,请告诉我,我会非常乐意的。\n换行符是读取器语法,它在读取时构造一个换行符对象。这可能有助于解决第二个问题:第一个'1 2'的类型应该是什么?