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
4

2 に答える 2

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。Common Lispのオブジェクトの詳細については、この優れたCLOSチュートリアル、PracticalCommonLispの第16章と第17章を確認してください。

また、将来、スタイルのアドバイスが必要な作業コードがある場合は、codereview.stackexchangeを確認してください。Lispレビュアーの数は少ないですが活発です。

于 2012-01-29T06:14:01.523 に答える
2

のスロットにリーダー関数を定義し、defclassそれをキー関数としてに提供できますremove-duplicates。たとえば、次の行をスロット定義に追加します。

:reader some-slot

次に、これを次の呼び出しで使用しますremove-duplicates

:key #'some-slot
于 2012-01-29T06:17:59.123 に答える