我一直试图通过阅读Peter Seibel的Beyond Exception Handling:条件和重启章节的实用Common Lisp,Kent Pitman 在Lisp语言家族中的条件处理以及其他一些参考资料来理解在Common Lisp中正确使用重启和处理程序.
根据我对重启的理解,它们是函数提供给调用者的选项,以便在遇到某些条件时选择函数的行为.
如果是这样的话,重新启动被视为功能的"公共接口"的一部分,并相应地记录下来?
毕竟,调用者必须知道重启以及他们做什么才能调用它们,对吗?我认为,摆脱调用者可能正在调用的重启将是一件坏事.
我已经阅读了几天时间的通用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))
我要做的就是打印所有奇数并跳过偶数错误,我的样本出了什么问题?有人帮忙吗?提前谢谢了!!
exception restart common-lisp conditional-statements condition-system
我有以下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. …我一直在阅读Peter Seibel Practical Common Lisp的优秀书籍,以解决我一直在做的与Common Lisp错误处理系统相关的研究.
虽然我已经阅读了书中的解释并试图在网上挖掘一些信息,但我无法理解STORE-VALUE和USE-VALUE重启的含义和用法.有人可以解释这些功能的目的是什么?
;;; Example of the STORE-VALUE and USE-VALUE restarts
(defun careful-symbol-value (symbol)
   (check-type symbol symbol)
   (restart-case (if (boundp symbol)
                     (return-from careful-symbol-value 
                                 (symbol-value symbol))
                     (error 'unbound-variable
                            :name symbol))
     (use-value (value)
       :report "Specify a value to use this time."
     value)
     (store-value (value)
       :report "Specify a value to store and use in the future."
       (setf (symbol-value symbol) value))))
lisp error-handling exception-handling common-lisp condition-system
我很有兴趣了解有关条件重启系统及其工作原理的更多信息.我不知道从哪里开始.我一直在寻找源代码,但想知道是否有更高级别的指南可用.
handler-case 是在 Common Lisp 中处理条件的关键,但 Ubuntu 18.04 上的 GCL 2.6.12 认为它是一个未定义的函数:
>(handler-case (error "test") (error (condition) condition))                   
                                                                               
Error: UNDEFINED-FUNCTION :NAME HANDLER-CASE                                   
Fast links are on: do (si::use-fast-links nil) for debugging                   
Signalled by EVAL.                                                             
UNDEFINED-FUNCTION :NAME HANDLER-CASE                                          
Broken at EVAL.  Type :H for Help.                                             
    1  Return to top level.                                                    
>>
对于 也是如此handler-bind。
GCL 手册中唯一与处理条件或错误相关的函数是 GCL 特定的universal-error-handler.
如何在 GCL 中处理条件,最好以其他 Lisps 支持的方式处理?
lisp common-lisp gnu-common-lisp condition-system ansi-common-lisp
我想捕获unbound-variable异常并避免它们,即时创建一些变量而不会中断执行。我正在尝试在以下代码中使用handler-bindwith invoke-restart:
(defmacro my-progn (&rest rest)
  `(handler-bind
    ((unbound-variable
      (lambda (x)
        (progn
          ;(format t "UNBOUND VAR: ~a~%"
          ;  (symbol-name (cell-error-name x)))
          (invoke-restart 'just-continue)))))
    (progn ,@(mapcar (lambda (x)
                      `(restart-case ,x (just-continue () "XXXX"))) rest))))
(my-progn
  (print "AAA")
  (print xxxx) ;; xxxx is unbound
  (print "BBB"))
结果是:
"AAA"
"BBB" 
但我想继续执行 second print,只需将未绑定的变量 xxxx 替换为字符串“XXXX”:
"AAA"
"XXXX"
"BBB" 
当然,我可以用 包裹语法树中的任何符号handler-bind,但我担心这会产生巨大的开销。
有没有办法只捕获unbound-variable异常并使用动态生成的值而不是丢失的变量继续执行代码?