删除重复项时将槽值指定为键

时间:2012-01-29 01:35:02

标签: lisp common-lisp clisp clos

以下代码可以满足我的需求:

 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 个答案:

答案 0 :(得分: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 :(得分:2)

您可以为defclass中的广告位定义阅读器功能,并将其作为remove-duplicates的关键功能。例如,将此行添加到插槽定义中:

:reader some-slot

然后在remove-duplicates

的调用中使用它
:key #'some-slot