Указание значения слота в качестве ключа при удалении дубликатов
Следующий код делает то, что я хочу:
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
2 ответа
Вы могли бы попробовать :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, а также главы 16 и 17 Practical Common Lisp для получения дополнительной информации об объектах в Common Lisp.
Кроме того, в будущем, если у вас есть рабочий код, для которого вы хотите получить совет по стилю, ознакомьтесь с https://codereview.stackexchange.com/. Есть небольшое, но активное население рецензентов Lisp.
Вы можете определить функцию чтения для слота в defclass
и предоставить это в качестве ключевой функции remove-duplicates
, Например, добавьте эту строку в определение слота:
:reader some-slot
а затем использовать это в вызове remove-duplicates
:
:key #'some-slot