Указание значения слота в качестве ключа при удалении дубликатов

Следующий код делает то, что я хочу:

 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
Другие вопросы по тегам