我读过普通的lisp" Practical Common Lisp"几天的异常处理章节,但我现在对样本和解释感到困惑,同时我试着编写一些测试样本,但它没有像我预期的那样工作,下面是我的测试样本。
条件定义
(define-condition evenp-error (error)
((text :initarg :text :reader text)))
定义打印奇数的函数
(defun filter-evenp (lst)
(dolist (x lst)
(if (not (evenp x))
(print x)
(error 'evenp-error :text x))))
重启功能
(defun skip-evenp (c) (invoke-start 'skip-evenp))
重启案例
(restart-case (filter-evenp (list 1 2 3 4 5))
(skip-evenp () nil))
我想做的就是打印所有奇数并跳过偶数错误,我的样本出了什么问题?有人帮忙吗?非常感谢提前!!
答案 0 :(得分:4)
您需要将RESTART-CASE
放在要重新开始执行的位置:
(defun filter-evenp (lst)
(dolist (x lst)
(restart-case
(if (not (evenp x))
(print x)
(error 'evenp-error :text x))
(skip-evenp () nil))))
然后你应该使用HANDLER-BIND
来处理错误:
(handler-bind ((evenp-error #'skip-evenp))
(filter-evenp (list 1 2 3 4 5)))
答案 1 :(得分:3)
Practical Common Lisp非常详细,但条件系统可能需要一些时间来习惯。您可能对Kent Pitman的文章感兴趣:Exceptional Situations in Lisp和Condition Handling in the Lisp Language Family。
What's a condition system and why do you want one?中引用了这些内容。还有许多其他参考文献lilke这个Wikibooks entry或C2 wiki的CommonLispConditionSystem条目。
RESTART-CASE
基本上说:
我将执行此表格,我不在乎它是否发出信号。但如果确实如此,并且您希望从这种情况中恢复过来,我可以通过不同的方式解决问题(重试,忽略等)。
您通常无法说明如何从呼叫点调用的代码中的错误中恢复。换句话说,filter-evenp
是谁应该用restart-case
包装代码以提供替代路径。对于您的示例,使用CERROR
就足够了,HANDLER-BIND
在建立CONTINUE
重启时发出错误信号。
(if (evenp x)
(cerror "Ignore even number" 'evenp-error :text x)
(print x))
作为练习,您可以尝试使用明确的(cerror ...)
结构替换restart-case
。
然后,如果您测试代码,您应该会看到调试器弹出并显示CONTINUE
重新启动。如果你定义了自己的重启,你可以用不同的名称命名,例如,但我认为CONTINUE
没问题。
在你的skip-evenp
函数中,你正在调用此时未建立的重启,我认为你对skip-evenp
感到困惑,同时命名了重启和函数。
通过调用重启来处理错误。
在这里,您希望发出错误信号的代码继续,因此您真的不想解开执行堆栈。这就是您必须使用integrate bootstrap module and ng2-select module to angular2 5min quickstart的原因。
(handler-bind ((evenp-error (lambda (e) (invoke-restart 'continue))))
(filter-evenp '(1 2 3 4)))
1
3
您可以将匿名lambda提取到自定义函数中,就像您一样。