LISP - 错误处理

LISP - 错误处理 首页 / LISP入门教程 / LISP - 错误处理

在Common LISP术语中,异常称为条件。

LISP中的条件处理机制以这样的方式处理这种情况:在调用堆栈上的上层代码可以继续工作的同时,条件被用来发出警告(如,通过打印警告)。

LISP中的条件处理系统包含三个部分:

  • Signalling  语句
  • Handling  语句
  • Restart     进程

处理条件

让我们举一个处理由零除条件引起的条件的示例,在这里解释概念。

您需要采取以下步骤来处理条件-

  • define-condition 宏用于定义条件,其语法如下-

(define-condition condition-name (error)
   ((text :initarg :text :reader text))
)
  • 宏根据:initargs 参数初始化新条件的slog。

在我们的示例中,以下代码定义了条件-

(define-condition on-division-by-zero (error)
   ((message :initarg :message :reader message))
)
  • 宏 handler-case 创建一个条件处理程序。处理程序案示例的基本形式-

(handler-case expression error-clause*)

其中,每个错误子句的形式为-

condition-type ([var]) code)
  • 重启阶段

    handler-bind 宏允许您提供重新启动函数,并允许您在不降低函数调用堆栈的情况下继续执行较低级别的函数。

    handler-bind 的基本形式如下-

(handler-bind (binding*) form*)

invoke-restart 宏查找并调用以指定名称作为参数的最近绑定的重新启动函数,您可以多次重启。

在此示例中,我们通过编写一个名为除法函数的函数来演示上述概念,如果除数参数为零,该函数将创建错误条件,我们有三个匿名函数,提供了三种实现方法:返回值1,发送除数2并重新计算或返回1。

创建一个名为main.lisp的新源代码文件,然后在其中键入以下代码。

链接:https://www.learnfk.comhttps://www.learnfk.com/lisp/lisp-error-handling.html

来源:LearnFk无涯教程网

(define-condition on-division-by-zero (error)
   ((message :initarg :message :reader message))
)
   
(defun handle-infinity ()
   (restart-case
      (let ((result 0))
         (setf result (division-function 10 0))
         (format t "Value: ~a~%" result)
      )
      (just-continue () nil)
   )
)
     
(defun division-function (value1 value2)
   (restart-case
      (if (/= value2 0)
         (/value1 value2)
         (error 'on-division-by-zero :message "denominator is zero")
      )

      (return-zero () 0)
      (return-value (r) r)
      (recalc-using (d) (division-function value1 d))
   )
)

(defun high-level-code ()
   (handler-bind
      (
         (on-division-by-zero
            #'(lambda (c)
               (format t "error signaled: ~a~%" (message c))
               (invoke-restart 'return-zero)
            )
         )
         (handle-infinity)
      )
   )
)

(handler-bind
   (
      (on-division-by-zero
         #'(lambda (c)
            (format t "error signaled: ~a~%" (message c))
            (invoke-restart 'return-value 1)
         )
      )
   )
   (handle-infinity)
)

(handler-bind
   (
      (on-division-by-zero
         #'(lambda (c)
            (format t "error signaled: ~a~%" (message c))
            (invoke-restart 'recalc-using 2)
         )
      )
   )
   (handle-infinity)
)

(handler-bind
   (
      (on-division-by-zero
         #'(lambda (c)
            (format t "error signaled: ~a~%" (message c))
            (invoke-restart 'just-continue)
         )
      )
   )
   (handle-infinity)
)

(format t "Done."))

当您执行代码时,它返回以下输出-

error signaled: denominator is zero
Value: 1
error signaled: denominator is zero
Value: 5
error signaled: denominator is zero
Done.

除了如上所述的"条件系统"以外,Common LISP还提供了各种函数,可以调用这些函数来发出错误信号。但是,在发出信号时,错误的处理取决于实现。

LISP函数

下表提供了常用函数,用于发出警告,中断,非致命和致命错误的信号,用户程序指定错误消息(字符串)。

无涯教程网

Sr.No.Function and 描述
1

error format-string &rest args

它预示着致命错误,不可能从这种错误中继续下去,因此错误将永远不会返回给调用者。

2

cerror continue-format-string error-format-string &rest args

它发出错误信号并进入调试器。但是,它允许在解决错误后从调试器继续执行程序。

3

warn format-string &rest args

它会显示一条错误消息,但通常不会进入调试器

4

break &optional format-string &rest args

它打印消息并直接进入调试器,而不会被编程的错误处理工具拦截

在此示例中,阶乘函数计算数字的阶乘;但是,如果参数为负,则会引发错误条件。

创建一个名为main.lisp的新源代码文件,然后在其中键入以下代码。

链接:https://www.learnfk.comhttps://www.learnfk.com/lisp/lisp-error-handling.html

来源:LearnFk无涯教程网

(defun factorial (x)
   (cond ((or (not (typep x 'integer)) (minusp x))
      (error "~S is a negative number." x))
      ((zerop x) 1)
      (t (* x (factorial (- x 1))))
   )
)

(write(factorial 5))
(terpri)
(write(factorial -1))

当您执行代码时,它返回以下输出-

120
*** - -1 is a negative number.

祝学习愉快!(内容编辑有误?请选中要编辑内容 -> 右键 -> 修改 -> 提交!)

技术教程推荐

黄勇的OKR实战笔记 -〔黄勇〕

从0打造音视频直播系统 -〔李超〕

Swift核心技术与实战 -〔张杰〕

图解 Google V8 -〔李兵〕

Spark核心原理与实战 -〔王磊〕

如何读懂一首诗 -〔王天博〕

如何讲好一堂课 -〔薛雨〕

Dubbo源码剖析与实战 -〔何辉〕

AI大模型企业应用实战 -〔蔡超〕

好记忆不如烂笔头。留下您的足迹吧 :)