2017-10-21 132 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

您的出色答案確實激發了一個後續問題,我在原始問題的末尾編輯了這個問題。如果我應該把它作爲一個單獨的問題發佈,請告訴我,我會很樂意。 –

相關問題