【问题标题】:Stopping the method from calling :after停止方法调用 :after
【发布时间】:2016-08-18 09:48:32
【问题描述】:

假设我有如下代码设置

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

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

【问题讨论】:

  • 您可能应该将燃料计算移至:AROUND 方法并将两个:AFTER 方法转换为主要方法。
  • @jkiiski 我如何阻止主要方法被调用?
  • 你只是不叫它。 :AROUND 方法必须手动使用 CALL-NEXT-METHOD 来调用主要方法,所以你可以有类似 (when (sufficient-fuel) (call-next-method)) 的东西。
  • 哦,好吧,但是不要在 main 方法的两边都调用 :around 吗?
  • 主要方法是通过调用CALL-NEXT-METHOD来调用的。

标签: common-lisp qualifiers multimethod


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    Common Lisp 还有catchthrow 用于非本地控制传输。 throw 将被 catch 捕获,在其 动态范围 内,使用特定的 catch 标签。 p>

    外部的:around 方法为标签exit-move 建立一个退出捕手。

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

    内部方法和主要方法一样,可以通过使用throw 和正确的catch 标签exit-move 将控制权转移到上面的catch。主要方法将始终在 inside around 方法 中使用,因此 catch 标记 将始终可以从中抛出。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-21
      • 1970-01-01
      • 2020-03-07
      相关资源
      最近更新 更多