Macro DEFINE-CONDITION

UP


Macro DEFINE-CONDITION

Macro DEFINE-CONDITION

構文

define-condition name (parent-type*) ({slot-spec}*) option*
=> name

slot-spec::= slot-name | (slot-name slot-option) 
slot-option::= [[{:reader symbol}* |  
               {:writer function-name}* |  
               {:accessor symbol}* |  
               {:allocation allocation-type} |  
               {:initarg symbol}* |  
               {:initform form} |  
               {:type type-specifier} ]] 
option::= [[(:default-initargs . initarg-list) |  
          (:documentation string) |  
          (:report report-name) ]] 
function-name::= {symbol | (setf symbol)} 
allocation-type::= :instance | :class 
report-name::= string | symbol | lambda expression 

引数と戻り値

name - シンボル
parent-type - コンディションの型の名前であるシンボル。 もしparent-typeが指定されなかったときは、 parent-typesはデフォルトで(condition)です。
default-initargs - キーワードと値のペアのリスト
slot-spec - スロットの名前か、 slot-nameに続いてゼロか複数のslot-optionを含むリスト。
slot-name - スロットの名前(シンボル)か、 スロットの名前のリストか、 【翻訳者注釈】名前とスロットのフォームのペアのリスト。
option - 下記のどれかのもの

※翻訳者注釈:名前とスロットフォームは許可されないかもしれません。

定義

define-conditionは新しいコンディションの型を定義します。 それはnameという名前であり、 parent-typeによって名付けられた型か あるいは型の集合のサブタイプになります。 各parent-type引数は、新しいコンディションの 直接的なスーパータイプとして指定されます。 新しいコンディションは各直接的なスーパータイプから スロットとメソッドが継承されます。

もしスロットに名前とスロットのフォームのペアが指定されたとき、 スロットのフォームは make-conditionに明に値が指定されなかったときの デフォルト値を提供するためにそのformを評価できます。 もしスロットフォームが指定されなかったときは、 そのスロットの値は実装依存の方法で初期化されます。 (※翻訳者注釈:名前とスロットフォームは許可されないかもしれません)

もしtypeが定義されるとき、 その型が同じ名前のスロットを持つ他のを継承するとき、 そのコンディションではただひとつのスロットだけが確保され、 そのスロットフォームはparent-typeによって継承された 他のスロットフォームによって上書きされます。 もしスロットフォームが指定されなかったときは、 継承されたスロットフォームは(あるならば)まだ見ることができます。

アクセッサはdefclassが使われたときと 同じルールに従って生成されます。

slot-optionの定義は下記の通り。

(defmethod print-object ((x c) stream)
  (if *print-escape* (call-next-method) (report-name x stream)))
(lambda (condition stream)
  (declare (ignore condition))
  (write-string report-name stream))

明に初期化されなかったスロットか、 あるいはデフォルト値を与えられなかったスロットについて 読み込みをしようとしたときの結果は未定義です。

スロットへの代入をsetfによって 行おうとしようとしたときの結果は未定義です。

もしdefine-conditionフォームがトップレベルフォームに現れたとき、 コンパイラーはその型の名前を有効なものとして認識しなければならず、 そのコンパイルされているファイル内の 後続のdefine-conditionが その他のコンディションのparent-typeに そのコンディションの型が参照できるようにしなければなりません。

例文

下記の例はpeg/hole-mismatchというコンディションの型の定義であり、 これはblocks-world-errorと呼ばれるコンディションの型を継承しています。

(define-condition peg/hole-mismatch 
                  (blocks-world-error)
                  ((peg-shape  :initarg :peg-shape
                               :reader peg/hole-mismatch-peg-shape)
                   (hole-shape :initarg :hole-shape
                               :reader peg/hole-mismatch-hole-shape))
  (:report (lambda (condition stream)
             (format stream "A ~A peg cannot go in a ~A hole."
                     (peg/hole-mismatch-peg-shape  condition)
                     (peg/hole-mismatch-hole-shape condition)))))

新しい型はpeg-shapehole-shapeというスロットを持っており、 よってmake-condition:peg-shape:hole-shapeという キーワードを受け付けます。 リーダーであるpeg/hole-mismatch-peg-shapepeg/hole-mismatch-hole-shapeは その型のオブジェクトを受付け、 :reportはその型の情報を出力します。

次のフォームはmachine-errorという名前のコンディションの型を定義しており、 これはerrorを継承しています。

(define-condition machine-error 
                  (error)
                  ((machine-name :initarg :machine-name
                                 :reader machine-error-machine-name))
  (:report (lambda (condition stream)
             (format stream "There is a problem with ~A."
                     (machine-error-machine-name condition)))))

次の定義の構築は、machine-errorのサブタイプとして 定義された新しいエラーのコンディションとして定義されたものであり、 機械が利用できないときに使われるものです。

(define-condition machine-not-available-error (machine-error) ()
  (:report (lambda (condition stream)
             (format stream "The machine ~A is not available."
                     (machine-error-machine-name condition)))))

この定義はまだより詳しいコンディションが定義でき、 machine-not-available-errormachine-nameの初期化フォームを提供していますが、 しかし新しいスロットも報告情報も提供していません。 ただmachine-nameのスロットのデフォルト初期化フォームだけ指定しています。

(define-condition my-favorite-machine-not-available-error
                  (machine-not-available-error)
  ((machine-name :initform "mc.lcs.mit.edu")))

注意してほしいのは、:reportオプションが与えられなくても、 その型の情報を報告する際には 継承されたmachine-not-available-errorの情報が使われます。

(define-condition ate-too-much (error) 
    ((person :initarg :person :reader ate-too-much-person)
     (weight :initarg :weight :reader ate-too-much-weight)
     (kind-of-food :initarg :kind-of-food
                   :reader :ate-too-much-kind-of-food)))
=>  ATE-TOO-MUCH
(define-condition ate-too-much-ice-cream (ate-too-much)
  ((kind-of-food :initform 'ice-cream)
   (flavor       :initarg :flavor
                 :reader ate-too-much-ice-cream-flavor
                 :initform 'vanilla ))
  (:report (lambda (condition stream)
             (format stream "~A ate too much ~A ice-cream"
                     (ate-too-much-person condition)
                     (ate-too-much-ice-cream-flavor condition)))))
=>  ATE-TOO-MUCH-ICE-CREAM
(make-condition 'ate-too-much-ice-cream
                :person 'fred
                :weight 300
                :flavor 'chocolate)
=>  #<ATE-TOO-MUCH-ICE-CREAM 32236101>
(format t "~A" *)
>>  FRED ate too much CHOCOLATE ice-cream
=>  NIL

影響

なし。

例外

なし。

参考

make-condition, defclass, 9.1. コンディションシステムの説明

備考

なし。


TOP, Github