停止方法调用 :after

Stopping the method from calling :after

假设我的代码设置如下所示

(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
)

现在假设我想将我的 space 船移到一个站点,但燃料计算导致船上的燃料量为负(即没有足够的燃料用于旅行)。

我有没有办法防止 :after 限定符被调用而不必发出错误信号?

如果我不停止呼叫,船将被移动到新位置而不会减去任何燃料,这基本上会破坏游戏。

你可以把燃料计算放在一个:AROUND方法中,把两个:AFTER方法变成主要方法。 :AROUND 方法必须使用 CALL-NEXT-METHOD 手动调用主要方法,因此您可以像 (when (sufficient-fuel) (call-next-method)) 那样仅在燃料充足时才调用它。

请注意,条件 不一定是错误。错误是一种特定情况,其中 如果没有某种形式的干预,正常的程序执行将无法继续正确进行。 条件系统也可用于其他情况

Common Lisp 还有 catchthrow 用于非本地控制转移。 throw 将在其 dynamic extent 内被 catch 捕获,使用特定的 抓标签.

外层 :around 方法为标签 exit-move.

建立出口捕捉器
(defmethod move :around (ship destination)
  (catch 'exit-move (call-next-method)))

内部方法,如主要方法,可以将控制转移到上面的 catch,方法是使用 throw 和正确的 catch 标记 exit-move。 primary 方法将始终在 inside around 方法 中使用,因此 catch 标记 将始终是可抛出的来自它。

(defmethod move (ship destination)
  (print (list :primary ship destination))
  (when (thing-happened-p)
   (throw 'exit-move nil)))