我对 Rebol 中的错误处理有点困惑。它具有 THROW 和 CATCH 结构:
>> repeat x 10 [if x = 9 [throw "Nine!"]]
** Throw error: no catch for throw: make error! 2
>> catch [repeat x 10 [if x = 9 [throw "Nine!"]]]
== "Nine!"
但是这种 throw 和捕获与传递给 TRY 上的/EXCEPT 细化的处理程序无关:
>> try/except [throw "Nine!"] [print "Exception handled!"]
** Throw error: no catch for throw: make error! 2
这对于 Rebol 的错误类型非常特殊:
>> try/except [print 1 / 0] [print "Error handled!"]
Error handled!
如果您愿意,您可以触发自己的错误,但不要像在其他语言中那样使用 THROW。抛出错误只会导致提示没有被捕获,就像任何其他值类型一样:
>> try/except [throw make error! "Error string"] [print "Error handled!"]
** Throw error: no catch for throw: make error! 2
您必须执行这些操作才能让评估器尝试执行错误类型的操作!导致它认为是“异常”:
>> try/except [do make error! "Error string"] [print "Error handled!"]
Error handled!
(注意:您可以 use pre-made errors apparently,例如
cause-error 'Script 'invalid-type function!
——更多信息请参见 system/catalog/errors
。)取消/EXCEPT 细化将使您将任何错误作为值接收。但是,这似乎无法区分是否调用了错误:
>> probe try [do make error! "Some error"]
make error! [
code: 800
type: 'User
id: 'message
arg1: "some error"
arg2: none
arg3: none
near: none
where: none
]
** User error: "Some error"
>> probe try [make error! "Some error"]
make error! [
code: 800
type: 'User
id: 'message
arg1: "Some error"
arg2: none
arg3: none
near: none
where: none
]
** User error: "Some error"
看起来 CATCH 在返回值和抛出值之间也没有类似的区别。但是有一个工具可以通过“命名 throw ”来解决这个问题:
>> code: [repeat x 10 [if x = 9 [throw/name "Nine!" 'number]]]
>> catch/name [do code] 'number
== "Nine!"
>> catch/name [do code] 'somethingelse
** Throw error: no catch for throw: make error! 2
那么现在问题来了:
"no catch for throw: make error! 2"
而不是更多信息?什么是make error! 2
? 最佳答案
"Is there a practical value to this separation? How does one decide whether to use THROW and CATCH or a DO of an error and handle it with TRY/EXCEPT?"
正如其他答案中所指出的那样,THROW 和 CATCH 形成了一个展开结构(非本地导出),它本身与控制流有关,不一定与错误处理有关。 THROW 和 CATCH 首先是影响控制流的直接方法,并且是其他自定义控制流构造的基本构建块。
因此,THROW 和 CATCH 当然也可以用于构建类似“异常处理”的错误系统,就像在许多当代主流语言中看到的那样,因为那些“异常处理”系统是非本地控制流的一个实例。
Rebol 的
error!
另一方面是信号和传播评估错误的主要方法。所以一般来说,决定很容易做出:如果你想引起错误,使用
error!
.如果要影响控制流以可控地展开,请使用 THROW/CATCH。关于术语的另外两点说明:
"Does this distinction have precedent in other languages"
是的,求值错误和非本地退出的区别在其他语言中已有先例,尤其是 Lisp 家族。一些快速引用:
catch
和 throw
对比 condition signaling catch
and throw
对比 error signaling block
对比 condition system "Why does it say "no catch for throw: make error! 2" instead of something more informative? What is the make error! 2?"
那是一个错误。 (很好的捕获!)我会说错误消息的核心(“no catch for throw”)已经提供了相当多的信息,但是
make error! 2
是一个错误(它应该在这里显示抛出的值。)"would /EXCEPT be better named /ON-ERROR or something?"
重命名
/EXCEPT
值得商榷。因此,我会说这是一个不适合 SO Q&A 的讨论,最好留给其他论坛。
关于exception - "errors/exceptions"和 "throw/catch"之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24412153/