我已获得以下lisp代码:
;;; hop.lisp
(defpackage #:hop
(:use #:cl ))
(in-package :hop)
(export 'hop)
(defun hop ()
(restart-case
(error "Hop")
(hop ()
(format t "hop"))))
我定义一个总是失败但提供重启的虚函数:hop。
在另一个包中,在此文件中:
;;; hip.lisp
(defpackage #:hip
(:use #:cl #:hop))
(in-package :hip)
(defun dhip ()
(hop:hop))
(defun hip ()
(handler-case
(hop:hop)
(error (e)
(declare (ignore e))
(format t "restarts: ~a~%" (compute-restarts))
(invoke-restart 'hop))))
我定义了从第一个包中调用函数(hop)的函数(hip)和(dhip)。
当我打电话(dhip)时,sbcl为我提供了一个提示,我可以选择使用我的重启跃点重新启动:
Hop
[Condition of type SIMPLE-ERROR]
Restarts:
0: [HOP] HOP
1: [RETRY] Retry SLIME REPL evaluation request.
2: [*ABORT] Return to SLIME's top level.
3: [ABORT] abort thread (#<THREAD "repl-thread" RUNNING {1009868103}>)
Backtrace:
0: (HOP)
1: (DHIP)
2: (SB-INT:SIMPLE-EVAL-IN-LEXENV (DHIP) #<NULL-LEXENV>)
3: (EVAL (DHIP))
--more--
这是我的预期。
然而,当我打电话(嘻哈)时,我的重启跃点没有列出(计算重启),并且无法使用它:(
No restart HOP is active.
[Condition of type SB-INT:SIMPLE-CONTROL-ERROR]
Restarts:
0: [RETRY] Retry SLIME REPL evaluation request.
1: [*ABORT] Return to SLIME's top level.
2: [ABORT] abort thread (#<THREAD "repl-thread" RUNNING {1009868103}>)
Backtrace:
0: (SB-INT:FIND-RESTART-OR-CONTROL-ERROR HOP NIL T)
1: (INVOKE-RESTART HOP)
2: ((FLET #:FUN1 :IN HIP) #<unused argument>)
3: (HIP)
4: (SB-INT:SIMPLE-EVAL-IN-LEXENV (HIP) #<NULL-LEXENV>)
5: (EVAL (HIP))
你知道可以做些什么来使它有效吗?
谢谢,
Guillaule
答案 0 :(得分:5)
这与包无关。
使用HANDLER-CASE,当处理程序运行时,堆栈已经解开。因此,在函数中建立的重启已经消失。
改用HANDLER-BIND。它在错误的上下文中运行处理程序,因此可以重新启动该函数。
示例:
(defun hip ()
(handler-bind ((error (lambda (e)
(declare (ignore e))
(format t "restarts: ~a~%" (compute-restarts))
(invoke-restart 'hop))))
(hop)))