2

以下のようなコード設定があるとします

(defgeneric move (ship destination))

(defmethod move (ship destination)
  ;; do some fuel calculation here
)

(defmethod move :after ((ship ship) (dest station))
  ;; do things specific to landing on a station here
)

(defmethod move :after ((ship ship) (dest planet))
 ;; do things specific to landing on a planet here
)

ここで、宇宙船をステーションに移動したいとしますが、燃料計算の結果、船の燃料がマイナスの量になります (つまり、移動に十分ではありません)。

:after必ずしもエラー状態を通知せずに修飾子が呼び出されないようにする方法はありますか?

私が電話を止めなければ、船は燃料を差し引かずに新しい場所に移動し、本質的にゲームが中断されます.

4

2 に答える 2

4

燃料計算をメソッドに入れ、2 つのメソッドをプライマリ メソッドに:AROUND変えることができます。メソッドはプライマリ メソッドを呼び出すために手動で使用する必要があるため、十分な燃料がある場合にのみ呼び出すなどの操作を行うことができます。:AFTER:AROUNDCALL-NEXT-METHOD(when (sufficient-fuel) (call-next-method))

于 2016-08-18T11:39:00.033 に答える
2

条件は必ずしもエラーではないことに注意してください。エラーとは、なんらかの介入なしでは通常のプログラムの実行を正しく続行できない特定の状態です。条件システムは、他の状況にも使用できます。

Common Lisp には、非ローカル制御転送用のcatchandもあります。スローthrowは、特定のcatch タグを使用して、その動的範囲内でcatchによってキャッチされます。

外側の:aroundメソッドは、タグの終了キャッチャーを確立しexit-moveます。

(defmethod move :around (ship destination)
  (catch 'exit-move (call-next-method)))

内部メソッドは、プライマリ メソッドと同様に、適切な catch タグcatchを使用して、上記の に制御を移すことができます。プライマリ メソッドは常にaround メソッドで使用されるため、catch タグは常にそこからスロー可能です。throwexit-move

(defmethod move (ship destination)
  (print (list :primary ship destination))
  (when (thing-happened-p)
   (throw 'exit-move nil)))
于 2016-08-20T10:34:59.670 に答える