【问题标题】:Semantics of the 'store-value' and 'use-value' restarts in the Common Lisp error handling system'store-value' 和 'use-value' 的语义在 Common Lisp 错误处理系统中重新启动
【发布时间】:2013-05-26 21:34:50
【问题描述】:

我一直在阅读 Peter Seibel Practical Common Lisp 的优秀书籍,以解决我一直在做的与 Common Lisp 错误处理系统相关的一些研究。

虽然我看了书上的解释,也试着在网上挖了一些资料,但我一直无法理解STORE-VALUEUSE-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))))

【问题讨论】:

    标签: exception-handling error-handling lisp common-lisp condition-system


    【解决方案1】:

    这是Lispworks中的一个例子。

    让我们定义一个类 foo 和一个插槽 bar

    CL-USER 26 > (defclass foo () (bar))
    #<STANDARD-CLASS FOO 4020001723>
    

    我们需要一个实例:

    CL-USER 27 > (make-instance 'foo)
    #<FOO 402000339B>
    

    现在我们尝试访问该对象的未绑定槽。请注意,* 访问的是先前评估的结果。

    CL-USER 28 > (slot-value * 'bar)
    

    我们收到一个错误并重新启动:

    Error: The slot BAR is unbound in the object #<FOO 402000339B>
        (an instance of class #<STANDARD-CLASS FOO 4020001723>).
      1 (continue) Try reading slot BAR again.
      2 Specify a value to use this time for slot BAR.
      3 Specify a value to set slot BAR to.
      4 (abort) Return to level 0.
      5 Return to top loop level 0.
    
    Type :b for backtrace or :c <option number> to proceed.
    Type :bug-form "<subject>" for a bug report template or :? for other options.
    

    2 号是use-value 重启,3 号是store-value 重启。

    让我们获取重启列表:

    CL-USER 29 : 1 > (compute-restarts)
    (#<RESTART ABORT 4020009EB3>       #<RESTART ABORT 4020009F53>
     #<RESTART NIL 402000585B>         #<RESTART USE-VALUE 40200058DB>
     #<RESTART STORE-VALUE 402000595B> #<RESTART ABORT 40200059DB>
     #<RESTART ABORT 4020005A7B>       #<RESTART ABORT 41700D2503>)
    

    在 LispWorks 中,我们可以通过 :cc 获取当前的条件对象。

    CL-USER 30 : 1 > :cc
    #<UNBOUND-SLOT 40200056F3>
    

    找到重启:

    CL-USER 31 : 1 > (find-restart 'store-value *)
    #<RESTART STORE-VALUE 402000595B>
    

    让我们打印出来:

    CL-USER 32 : 1 > (princ *)
    Specify a value to set slot BAR to.
    #<RESTART STORE-VALUE 402000595B>
    

    也适用于use-value 重启:

    CL-USER 33 : 1 > :cc
    #<UNBOUND-SLOT 402000B293>
    
    CL-USER 34 : 1 > (find-restart 'use-value *)
    #<RESTART USE-VALUE 402000B47B>
    
    CL-USER 35 : 1 > (princ *)
    Specify a value to use this time for slot BAR.
    #<RESTART USE-VALUE 402000B47B>
    

    【讨论】:

    • @GoZoner,这是为什么呢?这和“三叶草绿+1”一样好。
    【解决方案2】:

    也许是一个非常简单的解释:use-value 只会使用你给它的值一次,下次你碰到同一个地方时,它会再次出错。 store-value 只会要求您更正一次。

    想象一下这种情况:您正在迭代一个数组,并且在某些地方您输入了错误的索引变量,例如,j 而不是i。如果你选择use-value,一旦你点击了不存在的变量,它会一直询问你直到循环结束。但是如果你选择store-value,那么它会尝试使用你给它的任何东西,如果它有效,它将默默地继续直到循环结束。

    【讨论】:

    • 不是一个很好的例子,因为store-value 将分配j,但迭代更新i。错误会停止,但每次循环都会使用相同的值,而不是循环索引。
    猜你喜欢
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-20
    • 2014-06-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多