ErJ*_*Jab 2 erlang performance
假设我在Erlang中有一些函数fn1(),{ok, Result}如果函数执行成功并且{error, "ErrorReason"}出现错误则返回.
现在在另一个函数fn2()中我调用fn1()并且我需要检查fn1的结果并且仅在它是的时候继续{ok, Result}.
我想,我可以使用任何一种情况或尝试捕获.但效率是我的主要关注点,我想知道以下两种方法中的哪一种更有效:
try-catch 方法
fn2() ->
try
{ok, Result} = fn1(),
%Do something with Result
ok
catch
throw:Term -> Term;
exit:Reason -> {exit, Reason};
error:Reason -> {error,{Reason,erlang:get_stacktrace()}}
end.
Run Code Online (Sandbox Code Playgroud)
case 方法
fn2() ->
Res = fn1(),
case Res of
{ok, Result} ->
%Do something with Result
ok;
{error, Reason} ->
Reason
end.
Run Code Online (Sandbox Code Playgroud)
Gor*_*rie 10
你真的想尝试避免像瘟疫一样的尝试/捕获.这是Erlang中一个非常罕见的习语 - 实际上只用于几个特殊情况:
Try/catch在C++这样的语言中是必不可少的,其中应用程序在存在或错误时不稳定,但Erlang在这些情况下是稳定的 - 进程崩溃但不会导致系统崩溃.
您应该编写快乐路径,匹配返回值,如果应用程序偏离您的预期,那么让它崩溃.崩溃告诉您有问题,并告诉您修复它.
try/catch的问题在于它可以简单地掩盖问题,甚至更糟糕的是,将最终的崩溃从它应该发生的地方移开(在你已经包装的表达式中)并使其出现在其他地方 - 编程逻辑期望它在哪里已经超过了=这使得调试变得更加困难.
编程快乐路径并让它崩溃是第一次这样做时非常令人不安,感觉就像外出时没穿衣服,但实际上你很快就习惯了:)
case方法将更有效,因为它只是模式匹配,并且不涉及构建调用堆栈和东西.
在这两个示例中,您将在本地处理"错误",因此try catch中没有任何意义.您可能会看到有时类似于:
fn2() ->
{ok, Result} = fn1(),
%Do stuff with Result
ok.
Run Code Online (Sandbox Code Playgroud)
这里的意图是你使fn2()抛出一个坏匹配,如果fn1()没有返回ok.你让别人"上面"处理这个问题.例如,这可能会扼杀您的流程,并让您的主管创建一个新流程.