Erlang:在这种情况下哪个更有效 - 使用try catch或case语句?

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的问题在于它可以简单地掩盖问题,甚至更糟糕的是,将最终的崩溃从它应该发生的地方移开(在你已经包装的表达式中)并使其出现在其他地方 - 编程逻辑期望它在哪里已经超过了=这使得调试变得更加困难.

编程快乐路径并让它崩溃是第一次这样做时非常令人不安,感觉就像外出时没穿衣服,但实际上你很快就习惯了:)


Zed*_*Zed 8

case方法将更有效,因为它只是模式匹配,并且不涉及构建调用堆栈和东西.

在这两个示例中,您将在本地处理"错误",因此try catch中没有任何意义.您可能会看到有时类似于:

fn2() ->
  {ok, Result} = fn1(),
  %Do stuff with Result
  ok.
Run Code Online (Sandbox Code Playgroud)

这里的意图是你使fn2()抛出一个坏匹配,如果fn1()没有返回ok.你让别人"上面"处理这个问题.例如,这可能会扼杀您的流程,并让您的主管创建一个新流程.