停止调用方法:after

时间:2016-08-18 09:48:32

标签: common-lisp qualifiers multimethod

假设我有一个类似下面的代码设置

(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限定符被调用而不必发出错误信号?

如果我没有停止通话,则该船将被移至新位置而不会减去任何燃料,这实际上会破坏游戏。

2 个答案:

答案 0 :(得分:4)

您可以使用:AROUND方法进行燃料计算,并将两个:AFTER方法转换为主要方法。 :AROUND方法必须手动使用CALL-NEXT-METHOD来调用主要方法,因此您可以执行(when (sufficient-fuel) (call-next-method))之类的操作,只在有足够的燃料时才调用它。

答案 1 :(得分:2)

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

Common Lisp还有catchthrow用于非本地控制传输。 throw 将使用特定的 catch标记在其动态范围中由 catch 捕获。

外部:around方法为代码exit-move建立退出捕获器。

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

内部方法与主要方法一样,可以通过使用带有正确catch标记catch的{​​{1}}将控制权转移到上述throw。主要方法将始终使用 around方法,因此 catch标记将始终可以从中抛出。

exit-move