调度。 如果没有 -> 不调度-6ren">
gpt4 book ai didi

common-lisp - 如何使用方法组合减少代码重复但保持可能的早期返回

转载 作者:行者123 更新时间:2023-12-04 19:08:36 24 4
gpt4 key购买 nike

我得到了一组表示必须处理的消息的类。但是对于处理者来说只有有限的空位。因此,处理消息对象的处理程序的任何"dispatch"都必须首先检查是否有空闲位置。

如果有 -> 调度。

如果没有 -> 不调度并返回相应的消息

由于这部分代码在任何调度方法中都是相同的,我认为最好使用方法组合工具来强制执行,但我不知道如何。

在我当前的代码库中,我尝试使用 :before 方法,但显然您不能在这种情况下使用 return:

(defclass message () ((msg :initarg :msg :reader msg)))

(defclass message-ext (message)
((univ-time :initarg :univ-time :reader univ-time)))

(defparameter *open-handler* nil)

(defgeneric handle (message)
(:documentation "handle the given message appropriately"))

(defmethod handle :before ((message message))
(when (> (length *open-handler*) 1)
(return :full)))

(defmethod handle ((message message))
(push (FORMAT nil "dispatched handler") *open-handler*))

(defmethod handle ((message-ext message-ext))
(push (FORMAT nil "dispatched ext handler") *open-handler*))

(handle (make-instance 'message :msg "allemeineentchen"))

(handle (make-instance 'message-ext
:msg "rowrowrowyourboat"
:univ-time (get-universal-time)))

(handle (make-instance 'message-ext
:msg "gentlydownthestreet"
:univ-time (get-universal-time)))

Execution of a form compiled with errors.
Form:
(RETURN-FROM NIL FULL)
Compile-time error:
return for unknown block: NIL
[Condition of type SB-INT:COMPILED-PROGRAM-ERROR]

Restarts:
0: [RETRY] Retry SLIME interactive evaluation request.
1: [*ABORT] Return to SLIME's top level.
2: [TERMINATE-THREAD] Terminate this thread (#<THREAD "worker" RUNNING {100594F743}>)

Backtrace:
0: ((SB-PCL::FAST-METHOD HANDLE :BEFORE (MESSAGE)) #<unavailable argument> #<unavailable argument> #<unavailable argument>)
1: ((SB-PCL::EMF HANDLE) #<unavailable argument> #<unavailable argument> #<MESSAGE-EXT {1005961733}>)
2: (SB-INT:SIMPLE-EVAL-IN-LEXENV (HANDLE (MAKE-INSTANCE 'MESSAGE-EXT :MSG "gentlydownthestreet" :UNIV-TIME (GET-UNIVERSAL-TIME))) #<NULL-LEXENV>)
3: (EVAL (HANDLE (MAKE-INSTANCE 'MESSAGE-EXT :MSG "gentlydownthestreet" :UNIV-TIME (GET-UNIVERSAL-TIME))))
4: ((LAMBDA () :IN SWANK:INTERACTIVE-EVAL))

这种方法甚至是理智的,如果是,我该如何以一种有效的方式做到这一点? (我已经尝试过 return-from,结果相同)

最佳答案

我认为您应该使用 :around方法限定符:

(defmethod handle :around ((message message))
(if (cddr *open-handler*)
:full
(call-next-method)))

然而,更“lispy”的方法是使用 CL Condition System ,例如,这样的事情:
(define-condition too-many-messages (...) (...) ...)
(defun add-message (message)
(when (cddr *open-handler*)
(signal 'too-many-messages))
(push message *open-handler*))
(defmethod handle ((message message))
(add-message (FORMAT nil "dispatched handler")))

除了检查 handle 的返回值外,您还必须处理条件(例如,使用 handler-bind )功能。

附注。调用 length在列表上检查它是否足够长并不是一个好主意 - 尽管在您的情况下,当列表保证很短时,这可能更像是一个样式问题。

聚苯乙烯。使用 handle 这个词并不是一个好主意。作为函数的名称,因为 CL 具有包含它的函数(例如, handler-case )。除了使阅读您的代码的人感到困惑之外,这还会使您的代码中的搜索变得复杂。

关于common-lisp - 如何使用方法组合减少代码重复但保持可能的早期返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18384637/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com