常见的lisp异常处理(条件和重启)

时间:2016-03-23 12:24:59

标签: exception common-lisp conditional-statements restart condition-system

我读过普通的lisp" Practical Common Lisp"几天的异常处理章节,但我现在对样本和解释感到困惑,同时我试着编写一些测试样本,但它没有像我预期的那样工作,下面是我的测试样本。

  1. 条件定义

    (define-condition evenp-error (error) 
      ((text :initarg :text :reader text)))
    
  2. 定义打印奇数的函数

    (defun filter-evenp (lst)
      (dolist (x lst)
        (if (not (evenp x)) 
          (print x)
          (error 'evenp-error :text x))))
    
  3. 重启功能

    (defun skip-evenp (c) (invoke-start 'skip-evenp))
    
  4. 重启案例

    (restart-case (filter-evenp (list 1 2 3 4 5))
      (skip-evenp () nil))
    
  5. 我想做的就是打印所有奇数并跳过偶数错误,我的样本出了什么问题?有人帮忙吗?非常感谢提前!!

2 个答案:

答案 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 LispCondition 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提取到自定义函数中,就像您一样。