2012-01-29 162 views
4

下面的代碼時指定一個槽值作爲重點做什麼,我想:刪除重複

1 (defclass some-class() 
2 ((some-slot 
3  :initarg :somearg 
4  :initform (error ":somearg not specified")))) 
5 (defparameter *alpha* (make-instance 'some-class :somearg 3)) 
6 (defparameter *beta* (make-instance 'some-class :somearg 5)) 
7 (defparameter *gamma* (make-instance 'some-class :somearg 3)) 
8 (princ (slot-value *beta* 'some-slot)) (terpri) 
9 (defparameter *delta* (list *alpha* *beta* *gamma*)) 
10 (princ *delta*) (terpri) 
11 (princ (remove-duplicates *delta* 
12   :test #'equal 
13   :key (lambda (x) (slot-value x 'some-slot)))) 
14 (terpri) 
5 
(#<SOME-CLASS #x21C1D71E> #<SOME-CLASS #x21C1DAFE> #<SOME-CLASS #x21C1DC3E>) 
(#<SOME-CLASS #x21C1DAFE> #<SOME-CLASS #x21C1DC3E>) 

但是,有沒有辦法做到這一點,而無需編寫第13行的功能?有沒有一種簡捷的方式來指定類實例中的槽值?

當然,以下是語法錯誤,但它給出了我正在尋找的東西的一般概念。

1 (princ (remove-duplicates *delta* 
2   :test #'equal 
3   :key '(slot-value 'some-slot))) 
4 (terpri) 
*** - FUNCALL: (SLOT-VALUE 'SOME-SLOT) is not a function name; try using a 
     symbol instead 

回答

3

您可以試試:reader:accessor

(defclass some-class() 
    ((some-slot 
    :initarg :somearg :reader some-slot 
    :initform (error ":somearg not specified")))) 

應該讓你重新寫線11到13,

(princ (remove-duplicates *delta* :test #'equal :key #'some-slot)) 

也就是說,(some-slot x)相當於(slot-value x 'some-slot)如果有問題的插槽中有一個讀/存取。


後睡眠編輯:

您也不必費心設置:initform錯誤;如果您不指定默認值並且有人試圖讀取它,則插槽將默認執行此操作。如果你不要想要這個錯誤,你可以做一些類似於:initform nil的事情。查看這個出色的CLOS tutorial以及chapters 16 and 17 of Practical Common Lisp瞭解關於Common Lisp中對象的更多信息。

此外,如果您有工作代碼需要樣式建議,請檢查codereview.stackexchange。 Lisp評論員人數不多,但活躍。

+1

Inaimathi,我設置的原因:在initForm錯誤是觸發一個錯誤不當插槽被訪問時,但更早,當對象被創建時。這是爲我做的嗎? – 2012-01-31 05:25:08

+1

@Bill - 啊,我明白了。不,默認行爲是在訪問未設置的插槽時發生錯誤。你知道了。 – Inaimathi 2012-01-31 13:33:01

2

您可以爲defclass中的插槽定義閱讀器功能,並將其作爲remove-duplicates的關鍵功能。例如,該行添加到狹槽定義:

:reader some-slot 

然後在remove-duplicates在呼叫時使用這樣的:

:key #'some-slot