今天为了捕获错误问题,我已阅读erlang's错误和错误处理文档.
对于生成的错误类型,有两种类型,一种是exit,另一种是throw.在点击我的源代码之后,throw and exit表达式已经集中了.
两者都相似,似乎只是捕捉匹配表达是不同的.
(emacs@chen-yumatoMacBook-Pro.local)30> catch throw ({aaa}).
{aaa}
(emacs@chen-yumatoMacBook-Pro.local)31> catch exit ({aaa}).
{'EXIT',{aaa}}
(emacs@chen-yumatoMacBook-Pro.local)32> catch gen_server:call(aaa,{aaa}).
{'EXIT',{noproc,{gen_server,call,[aaa,{aaa}]}}}
Run Code Online (Sandbox Code Playgroud)
你能告诉我什么时候使用throw以及何时使用exit?
rvi*_*ing 16
有3类,可以用被捕获try ... catch:throw,error和exit.
throw是生成使用throw/1并且旨在用于非本地返回,并且除非未捕获(当您收到nocatch错误时),否则不会生成错误.
error系统检测到错误时生成.您可以使用显式生成错误error/1.例如,系统还包括生成的错误值中的堆栈跟踪{badarg,[...]}.
exit使用exit/1并且意图表示该过程将死亡.
error/1和之间的区别exit/1不是那么大,它更多的是由错误产生的堆栈跟踪增强的意图.
实际上,它们之间的区别实际上更明显catch ...:当throw/1使用when时,catchjust返回抛出的值,正如非本地返回所期望的那样; 当error/1被使用,则在catch返回{'EXIT',Reason}其中Reason包含堆栈跟踪; 而from exit/1 catch也返回,{'EXIT',Reason}但Reason只包含实际的退出原因.try ... catch看起来它等同于他们,但他们是非常不同的.
[更新]
Robert Virding指出,我忽略了抛出与错误之间的重要区别.此编辑仅供记录!
throw error将用于throw其他语言中使用的地方.您的代码检测到正在运行的进程中的错误,该错误表示异常error/1.相同的进程捕获它(可能在堆栈中更高),并且错误将在同一进程中处理.error总是带来一个堆栈跟踪.
throw用于不发出错误信号,而只是从深层嵌套函数返回一个值.由于它展开堆栈,因此调用throw将抛出的值返回到捕获的位置.就像在这种情况下一样error,我们正在捕获抛出的东西,只有被抛出的东西不是错误,而只是一个值传递给堆栈的值.这就是为什么throw不会带来堆栈跟踪的原因.
作为一个人为的例子,如果我们想要exists为列表实现一个函数(类似于那个list:any),并且作为一个练习而没有自己进行递归,并使用just list:foreach,那么throw可以在这里使用:
exists(P, List) ->
F = fun(X) ->
case P(X) of
true -> throw(true);
Whatever -> Whatever
end
end,
try lists:foreach(F, List) of
ok -> false
catch
true -> true
end.
Run Code Online (Sandbox Code Playgroud)
抛出但未捕获的值被视为error:nocatch将生成异常.
EXIT将在"放弃"时由进程发出信号.在父进程处理退出,而孩子只是过程死亡.这是Erlang let-it-crash理念.
因此exit/1,EXIT不会被捕获在同一个过程中,而是留给父母.error/1错误是过程的本地错误 - 即,过程本身发生了什么以及如何处理错误; throw/1用于跨越堆栈的控制流.
[UPDATE]
exit/2- 用Pid一个进程发送EXIT来调用.
exit/1暗示父进程.