我应该在 Erlang 中使用 try catch 还是应该传回错误标记?
我正在用 Erlang 进行编码,但我有点不确定如何处理错误,尤其是在看到 Erlang 总是返回的丑陋错误之后。
我应该在 Erlang 中使用 try catch 还是应该传回错误标记?
I'm coding in Erlang and a I am bit unsure about how to approach error handling, especially after seeing the ugly errors Erlang always returns.
Should I use try catch in Erlang or should I pass back an error token?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在顺序 Erlang 中执行异常处理有三种基本方法:
throw(Term)
)erlang:error(Reason)
)exit( Reason)
)抛出用于非本地返回和您期望能够处理的某些类型的异常(可能是因为它们经常发生)。当这个问题被提出时,你应该在它超出你的模块之前尝试阻止它。它在 stdlib 中使用的通常方法是抛出一个
{error, Reason}
类型的元组,它将被try...catch< 中的顶级函数捕获。 /code> 在将元组返回给用户之前。然后,用户可以根据该返回值决定要做什么。
另一方面,错误指向不可恢复的异常。他们通常会要求用户更改他的代码。它们包括运行时错误,例如无法匹配的
if
或case ... of
分支、无法匹配或不存在的函数等。此错误的原因是崩溃,并且在大多数情况下不应在进程本地捕获或处理(让主管或监视进程获取错误消息,然后为您记录它或在界面级别为用户处理它) 。当您特别希望进程终止时,可以使用退出。有时有点不清楚何时使用退出或错误,但我得到的提示是区分意图。
错误和退出很少应该被捕获并按顺序处理(你真的必须确保你知道如何修复问题!),因为其他进程已经就位来处理它。让它崩溃吧。
(更多详细信息:http://learnyousomeerlang.com/errors-and-exceptions)
下一个级别是在多进程环境中处理错误时。此时执行操作的标准方法是将进程链接在一起(和/或使用主管)以获取死进程及其原因:重新启动它们,记录消息,进行维护,在系统不断运行时进行升级。
您将获得一个针对多个进程的新异常函数:
exit(Pid, Reason)
。这使您可以在另一个进程上调用“退出”。在这种情况下,必须通过在监视进程中设置process_flag(trap_exit, true)
来完成错误处理,之后您可以通过标准receive
表达式获取退出信号。请注意,一种特殊类型的退出,即
exit(Pid, Kill)
将终止进程,而无法捕获它。然后,链接到Pid
的其他进程应该收到{'EXIT',killed}
形式的信号。使用监督树可以确保程序持续运行。为了确保不会破坏任何东西,尽早崩溃也很重要;有问题的代码越早停止运行,清理起来就越容易。
There are three basic ways to do exception handling in sequential Erlang:
throw(Term)
)erlang:error(Reason)
)exit(Reason)
)Throws are to be used for non-local returns and some kinds of exception you expect to be able to handle (maybe because they occur often). When that one is raised, you should try and stop it before it gets outside your module. The usual way it is used in the stdlib is to throw a tuple of the kind
{error, Reason}
which will be caught by a top-level function in atry...catch
before returning the tuple to the user. The user can then decide what to do based on that return value.Errors, on the other hand, point to non-recoverable exceptions. They're usually going to require the user to change his code. They include runtime errors like
if
orcase ... of
branches that can't be matched, functions that can't match or don't exist, etc. The purpose of this error is to crash, and should not be caught or handled locally to the process in most cases (have a supervisor or monitoring process pick up the error message and then log it for you or handle it for the user at the interface level).Exits are to be used when you specifically want the process to terminate. It's sometimes a bit unclear when to use exits or errors, but the tip I've been given is to differentiate the intent.
Errors and exits seldom should be caught and handled sequentially (you've really got to be sure you know how to fix things!), as other process are in place to deal with it. Let it crash.
(more details: http://learnyousomeerlang.com/errors-and-exceptions)
The next level is when dealing with errors in a multi-process environment. The standard way to do things at that point is to link processes together (and/or use supervisors) to pick up dead processes and the reason why they did: restart them, log the message, do your maintenance, upgrade while the system keeps rolling.
You get a new exception function for multiple processes:
exit(Pid, Reason)
. This lets you call 'exit' on another process. In this case, error handling has to be done by settingprocess_flag(trap_exit, true)
in the monitor process, after which you can get exit signals through a standardreceive
expression.Note that a special kind of exit, namely
exit(Pid, kill)
will terminate a process without any possibility to catch it. Other processes linked toPid
should then receive a signal of the form{'EXIT', killed}
.Using supervision trees is how you make sure your programs keep running. Crashing early is also essential in order to make sure you won't corrupt anything; the earlier problematic code stops running, the easier it is to clean it all up.
Erlang 的基本原理是:
我发现避免所谓的防御性编程非常有用。这个概念在 Erlang 编程规则页面中有更详细的解释:
http://www .erlang.se/doc/programming_rules.shtml#HDR11
此外,即使一些 Erlang 错误可能有点神秘,处理它们的一个好方法是跟踪它们! Erlang 中的跟踪非常简单。查看此快速参考:
http://aloiroberto.wordpress。 com/2009/02/23/tracing-erlang-functions/
或者直接参考官方文档。
这就是说,我完全同意@jdupont。
The basic principle in Erlang is:
I found quite useful to avoid the so called defensive programming. The concept is explained in a bit more detail in the Erlang Programming Rules page:
http://www.erlang.se/doc/programming_rules.shtml#HDR11
Moreover, even if some of the Erlang errors can be a bit cryptic, a nice way to deal with is trace them! Tracing in Erlang is pretty simple. Have a look to this quick reference:
http://aloiroberto.wordpress.com/2009/02/23/tracing-erlang-functions/
or simply refer to the official documentation.
This said, I fully agree with @jdupont.
如果您可以在本地明智地处理异常,请捕获它并处理它,否则就让它“冒泡”。
如果您知道对于特定异常无能为力,那么“快速失败”。
If you can deal with the exception sensibly locally, catch it and treat it or else let it "bubble up".
If you know nothing can be done with a particular exception, then "fail fast".
我认为这很大程度上是功能的用户想要做什么的问题。标准中的一个相当低级别的文件 API 的示例是:打开文件并获取文件句柄,从传入文件句柄的文件中读取数据,然后关闭传入文件句柄的文件。
更高级别的 API 是
file:consult/1
,您可以在其中传递文件名并期望将内容解析为 Erlang 术语。中间立场是 lisp 中常见的with-open-file
函数,您可以在其中传入一个函数,该函数以当时打开的文件句柄作为参数进行调用。尽管它们都打开并访问文件,但期望使得使用异常而不是错误标记来描述事情的进展变得越来越明智。
您希望允许程序员为成功案例编写可读的代码。如果您期望文件不存在,则返回值的简单情况往往比异常处理更漂亮。如果你的成功案例是假设文件存在并只是读取它,那么一旦它不存在,异常将确保你崩溃。
因为你认为 Erlang 有丑陋的错误消息而选择任何特定的方法似乎不是一个好的指导方针。
I think this is largely a question of what the user of the function wants to do. An example of a quite low level file API is the standard: open a file and get a file handle, read from the file passing in the file handle, and close the file passing in the file handle.
A higher level API is
file:consult/1
where you pass in a filename and expect to get the content back parsed as Erlang terms. A middle ground would be awith-open-file
function as is common in lisp, where you pass in a function that is called with the then open file handle as its argument.Even though they all open and access files, the expectation makes it more and more sensible to use exceptions instead of error tokens to describe how things went.
You want to allow the programmer to write readable code for the successful case. If you expect that a file wont exist, a simple case on the return value tends to be prettier than exception handling. If your successful case is to assume the file exist and just read it, then an exception will make sure you crash as soon as it doesn't hold up.
Choosing any particular approach because you think Erlang has ugly error messages does not seem like a good guideline.