2017-10-21 130 views
0

这个问题是关于sbcl - 或者我原本以为。问题:什么时候角色不是角色?请看下面的代码:sbcl(和clisp):何时一个角色不是角色? (使用defconstant)

(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的回答,我本来期望它产生了一些关于符号,而不是一个字符,第二个表达式。

+1

#\换行符是读取器的语法,它构造在读时间换行符对象。 –

+0

有些东西可能会帮助你解决第二个问题:'(类型(第一'(1 2)))'应该是什么? – tfb

回答

8

主要混乱来自

  1. 列表的双重目的:数据和代码。评估(+ a b)是代码,这里是一个函数调用。 (quote (+ a b))'(+ a b)都是数据,因为它们评估的是引用的文字数据。
  2. 阅读已经创建对象。已经将#\newline读为角色对象。它是内置语法:Sharpsign Backslash它不是一个字符串,不是一个符号,也不是一些未知的数据。它被看作类型字符(我在这里使用文字字符对象)的对象,也可以只是说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 
5

问题是,您正在引用“字符列表”。所以不是一个字符列表,而是一个符号列表。也就是说

(defun st (the-string) 
    (string-trim (list +asc-lf+ +asc-space+) the-string)) 

该错误消息,在此提示当它说

值 + ASC-LF +的类型不是 CHARACTER的

和不

值 #\ Newline不是类型CHARACTER

+0

您的出色答案确实激发了一个后续问题,我在原始问题的末尾编辑了这个问题。如果我应该把它作为一个单独的问题发布,请告诉我,我会很乐意。 –

相关问题