Common Lisp状况系统(condition system)的学习和理解

• 状况系统是这样的:底层代码产生状况---》中层代码制定多种恢复策略-》上层代码处理并选择中层的恢复策略

• 将从错误中恢复的代码与决定选择如何恢复进行分离,也就是说,错误恢复方法在底层提供了,选择哪个进行恢复的选择权交给高层函数。

• 状况系统使得我们在写底层功能函数时只关注函数功能即要完成的事情,而对于错误的恢复方法都在中下层提供,高层拥有最后的选择权。另外,状况系统使得我们在遇到错误的时候不必转到调试器而停止,而是进入预想的错误处理的方法中。

• 以下是处理函数对抛出的error的简单的处理方式:
(define-condition malformed-log-entry-error (error)
((test :initarg :text :reader text)))

(defun parse-log-entry (text)
(if (evenp text)
text
(error 'malformed-log-entry-error :text text)))

(defun parse-log-file ()
(loop for i from 1 to 10 do
(handler-case (parse-log-entry i)
(malformed-log-entry-error(var) (text var))))

结果为:
((1 "odd") (2 "even") (3 "odd") (4 "even") (5 "odd") (6 "even") (7 "odd") (8 "even") (9 "odd") (10 "even"))

• restart-case可以有多个,每次抛出error,调用栈都会跳出多个restart让你选择,处理的方法是调用invoke-restart来主动选择重启策略,这个选择我们在高层函数中利用handler-bind对错误类型和处理函数进行绑定,这就使得我们可以在中层和底层代码中制定多种重启策略,在不同的高层函数中选择不同的处理策略,以下是我改写的书上例子,目的是要理解多个restart-case的运行方式:
(define-condition malformed-log-entry-error (error)
((test :initarg :text :reader text)))

(defun parse-log-entry (text)
(if (evenp text)
(list text "even")
(error 'malformed-log-entry-error :text text)))

(defun parse-log-file ()
(loop for i from 1 to 10
for entry = (restart-case (parse-log-entry i);;提供三个restart-case
(skip-log-entry () "a")
(use-value (v) (list v "odd"))
(reparse-entry (fixed-text) (parse-log-entry fixed-text)))
when entry collect it))

(defun analyze-log ()
(print (parse-log-file)))

(defun skip-log-entry (c)
(let ((restart (find-restart 'skip-log-entry)))
(when restart
(invoke-restart restart))))

(defun use-value-p (c)
(use-value (text c)))

(defun reparse-log-entry (c)
(let ((reparse (find-restart 'reparse-entry)))
(when reparse
(invoke-restart reparse (+ (text c) 11)))))

;;在高层函数中,根据不同的情况选择不同的再启动策略
(defun log-analyzer-skip ()
(handler-bind ((malformed-log-entry-error #'skip-log-entry))
(analyze-log)))

(defun log-analyzer-use ()
(handler-bind ((malformed-log-entry-error #'use-value-p))
(analyze-log)))

(defun log-analyzer-reparse ()
(handler-bind ((malformed-log-entry-error #'reparse-log-entry))
(analyze-log)))



• 分别运行log-analyzer-skip log-analyzer-reparse log-analyzer-use,结果为:

(("a" "odd") (2 "even") ("a" "odd") (4 "even") ("a" "odd") (6 "even") ("a" "odd") (8 "even") ("a" "odd") (2 "even") )

((12 "even") (2 "even") (14 "even") (4 "even") (16 "even") (6 "even") (18 "even") (8 "even") (20 "even") (10 "even"))

((1 "odd") (2 "even") (3 "odd") (4 "even") (5 "odd") (6 "even") (7 "odd") (8 "even") (9 "odd") (10 "even"))

可见,对于同一种condition,我们在不同的高层函数中选择不同的策略进行处理,得到了不同的结果。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值