2014-01-11 44 views
3

我在sbcl 1.1.14中試過下面的代碼,但是看起來類型檢查忽略了向量元素的聲明。如何在sbcl(或common lisp)向量中指定元素類型?

(defun test (vec) 
    (declare (type (vector integer) vec)) 
    (format nil "~a~&" (elt vec 0))) 

任何提示?謝謝!

+0

您可以詳細說明您的意思嗎*類型檢查忽略聲明*?當我運行你的代碼並執行'(test#(1 2 3))'時,我得到了'1'。當我做'(test'(1 2 3))''我得到'值(1 2 3)不是類型(VECTOR INTEGER).'正如所料。我正在使用'sbcl'版本1.0.57。 – lurker

+0

@mrbatch嘗試(測試#('1 2 3))返回'1沒有警告/錯誤對我來說(SBCL 1.1.14) – verdammelt

+0

@verdammelt啊是的,我明白了。還有'(test#(a b c))'不會返回錯誤,只是'A' – lurker

回答

10

請注意,首先將聲明作爲類型檢查不是由標準ANSI Common Lisp提供的。這是CMUCL引入的一個擴展。 SBCL是CMUCL的後代。

Common Lisp類型系統適用於向量和數組的方式稍有不同。

元素類型

正在使用元素類型創建數組。這意味着Lisp系統將創建一個可以存儲該類型元素的數組。但Common Lisp並不要求每個元素類型都有專門的數組版本。如果數組的特定版本不可用,那麼元素類型將升級爲下一個「更大」類型。

示例元素類型升級

CL-USER 14 > (upgraded-array-element-type '(unsigned-byte 1)) 
(UNSIGNED-BYTE 1) 

CL-USER 15 > (upgraded-array-element-type '(unsigned-byte 2)) 
(UNSIGNED-BYTE 2) 

所以存在用於(unsigned-byte 1)(unsigned-byte 2)優化陣列的版本。

CL-USER 16 > (upgraded-array-element-type '(unsigned-byte 3)) 
(UNSIGNED-BYTE 4) 

OOPS!沒有針對(unsigned-byte 3)進行優化的陣列。如果你要求這樣一個數組,你會得到一個稍大的數組,對於(unsigned-byte 4)

CL-USER 17 > (upgraded-array-element-type '(unsigned-byte 4)) 
(UNSIGNED-BYTE 4) 

CL-USER 18 > (upgraded-array-element-type '(unsigned-byte 5)) 
(UNSIGNED-BYTE 8) 

CL-USER 19 > (upgraded-array-element-type 'integer) 
T 

上面顯示沒有整數的特殊數組。你會得到一個通用數組。

代碼

(defun test (vec) 
    (declare (type (vector integer) vec)) 
    (format nil "~a~&" (elt vec 0))) 

所以在這裏你的宣言的真正含義是:

變量vec勢必能舉行integer數字的載體。

,這並不意味着:

可變vec綁定到其中僅helds integer號的向量。在我的Lisp

CL-USER 21 > (typep '#(a "b" #\c) '(vector integer)) 
T 

以上返回true,因爲向量是一個普遍的載體,它可以存儲整數。所以它檢查向量的類型,但它並不關心向量的內容實際上是否都是整型。它只是說,矢量可以包含整數。

基於謂詞型檢查

Common Lisp的允許類型聲明使用謂詞。

CL-USER 28 > (defun vector-of-numbers-p (vector) 
       (and (typep vector 'vector) 
        (every 'integerp vector))) 
VECTOR-OF-NUMBERS-P 

CL-USER 29 > (typep '#(a "b" #\c) '(satisfies arrayp)) 
T 

CL-USER 30 > (typep '#(a "b" #\c) '(satisfies vector-of-numbers-p)) 
NIL 

CL-USER 31 > (typep '#(1 2 3) '(satisfies vector-of-numbers-p)) 
T 

但在編譯時檢查?可能不會。

+0

非常感謝!非常明確和翔實的解釋。我現在更瞭解陣列。這真的不直截了當。這種設計很有趣,儘管通常需要具有一種特定類型的元素的數組(矢量),至少對於科學計算來說。希望普通的lisp可以提供專門用於任何類型的數組。 – user3185284

+0

@ user3185284:這是如何需要的?什麼樣的科學需要它?請注意,_type_可以是「所有素數」或「至少有4個門的所有紅色汽車」。也許你正在考慮_classes_? – Svante