Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Exception 公共lisp异常处理(条件和重新启动)_Exception_Common Lisp_Conditional Statements_Restart_Condition System - Fatal编程技术网

Exception 公共lisp异常处理(条件和重新启动)

Exception 公共lisp异常处理(条件和重新启动),exception,common-lisp,conditional-statements,restart,condition-system,Exception,Common Lisp,Conditional Statements,Restart,Condition System,我已经阅读了common lisp“实用common lisp”异常处理章节好几天了,但我现在对示例和解释感到非常困惑,同时我尝试编写一些测试示例,但它没有像我预期的那样工作,下面是我的测试示例 条件定义 (define-condition evenp-error (error) ((text :initarg :text :reader text))) 定义打印奇数的函数 (defun filter-evenp (lst) (dolist (x lst) (if (not

我已经阅读了common lisp“实用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))
    

  • 我想做的就是打印所有奇数,跳过偶数错误,我的样本有什么问题?有人帮忙吗?非常感谢

    您需要将您的
    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)))
    
    非常详细,但条件系统可能需要一些时间才能适应。你可能会对肯特·皮特曼的文章感兴趣:和

    这些在中引用。还有许多其他的参考文献,比如这个或C2维基的条目

    定义重新启动 A基本上说:

    我将执行此表单,我不在乎它是否表示条件。但如果确实如此,并且您希望从这种情况中恢复过来,我可以用以下几种不同的方法来解决这个问题(重试、忽略等)

    通常无法说明如何从调用点调用的代码中的错误中恢复。换句话说,
    filter evenp
    应该用
    restart case
    包装代码,以提供替代路径。对于您的示例,使用就足够了,它在建立
    继续
    重新启动时发出错误信号

    (if (evenp x)
      (cerror "Ignore even number" 'evenp-error :text x) 
      (print x))
    
    作为练习,您可以尝试将
    (cerror…
    替换为显式
    重新启动案例
    构造

    然后,如果您测试代码,您应该会看到调试器弹出并显示
    继续
    重新启动。如果定义了自己的重新启动,则可以使用不同的名称

    调用重启 在您的
    skip evenp
    函数中,您调用了一个此时未建立的重启,我认为您与
    skip evenp
    命名重启和函数混淆了

    您应该做的是通过调用重启来处理错误

    在这里,您希望发出错误信号的代码继续,因此您确实不希望解除执行堆栈。这就是为什么你必须使用


    当然,您可以像以前一样将匿名lambda提取到自定义函数中。

    您提供的解决方案正是我想要的,但我仍然对重新启动的内容感到困惑,让我尝试找到更多的资料来解决它,谢谢@用户2015063如果用户是有用的,考虑用绿色复选标记接受它。如果这对你有帮助的话,我会添加更多的参考资料。谢谢你的回复,我仍然不确定“skip-evenp”指的是哪里。to?
    #“SKIP-EVENP
    指的是该名称的函数(这就是
    #“
    的意思)。
    HANDLER-BIND
    告诉它通过调用函数
    SKIP-EVENP
    @user2015063
    #来处理任何
    EVENP-ERROR
    是一个读卡器宏:上述函数相当于
    (函数跳过事件)
    并使用特殊运算符引用按词汇绑定到跳过事件符号的函数对象。@jkiiski非常感谢,我通过google搜索了更多示例后终于找到了它,
    (handler-bind ((evenp-error (lambda (e) (invoke-restart 'continue))))
      (filter-evenp '(1 2 3 4)))
    1
    3