zoukankan      html  css  js  c++  java
  • [Erlang01] 使用catch与try catch避免嵌套nest_case

    catch 如此好用,为什么官方还是推荐用try catch?

    1. catch 的用法非常简单:

    catch case do_check(Test) of
           {ok,Result} -> do_thing(Result);
           {error,ErrReason} -> do_error(ErrReason)
    end.
    
    do_check(Test) ->
       case Test of
            1 -> erlang:throw({error,to_small});
            2 –> {ok,2};
            9 -> erlang:throw({error,too_big})
       end,
    以上用法的优点是:非常简单&&do_check/1里面如果有nest_case也可以处理掉,
    缺点也非常明显:
    1.1 如果Test是除1,2,9以外的值时会发生case_clause,catch也不能匹配;
    1.2 do_check/1要在外层用Catch[这个check要由调用者来确定用法],这就对调用者有更高的要求。
    2. try catch用法:
    %% 首先对FuncOrExpressionSequence求值
    %% 如果没有产生异常则顺序进行Patterm匹配, 匹配成功后执行后面的表达式
    %% 如果有异常抛出, 则顺序匹配ExPattern(ExceptionType是throw、exit、error中的一个, 默认为throw)
    %% after块中的代码用于清理工作,绝对会执行
    try FuncOrExpressionSequence of
        Pattern1 [when Guard1] ->Expressions1;
        Pattern2 [when Guard2] ->Expressions2;
        ...
    catch
        ExceptionType: ExPattern1 [when ExGuard1] ->ExExpressions1;
        ExceptionType: ExPattern2 [when ExGuard2] ->ExExpressions2;
        ...
    after
        AfterExpressions
    end.
    也可以把after后面的去掉:
    %% 将三种异常方式依次捕获
    try F
    catch
        throw: X ->ExExpressions1;
        exit: X  ->ExExpressions2;
        error: X ->ExExpressions3
    end.

    那么根据这用法:可以把Catch的用法改写会:

    case do_check(Test) of
           {ok,Result} -> do_thing(Result);
           {_,ErrReason} -> do_error(ErrReason)
    end.
    
    do_check(Test) ->
     try 
          case Test of
              1 -> erlang:throw({error,to_small});
              2 –> {ok,2};
              9 -> erlang:throw({error,too_big})
         end
    catch 
         throw:X -> {throw,X};
         exit:X -> {exit,X};
        error:X -> {error,X}
    end.

    从上面可以看出:所有的异常都被正确的处理了且do_check/2对调用者也是透明的!真是太棒了!

    在stack overflow上这个答案才能是最佳实践:

    how to write_elegantly_check_function

    从上面测试结果来看,try catch确定会消耗一点性能,所以如果条件不复杂且频繁调用的check,就不要用try catch了:)

    2014年5月22日 12:10:16 补充:

    1.不用try cathc怎么写一个复杂的Case :

    case {check_name(Name),check_passwd(Passwd),check_url(Url) } of
        {true ,true ,true} ->
                         do_next_work();
        {false,_,_} ->
                         check_error(name);
        {_,false,_} ->
                       check_error(passwd);
        {_,_,false } ->
                      check_error(url)
          end.

    2. 有时会在一个重要的进程 时最底层做了try catch ,以防止carsh ,那我们在写上层逻辑时,也会做复杂的判定,又加了一个try catch,

    例如:

    %%在try catch中再套try catch.
    init_data(Data) ->
        try
            Data1 = init_data2(Data),
            after_init(Data1)
        catch _:_ -> error
        end.
    init_data2(Data) ->
        try
            check_init_data(Data)
        catch _:_ -> init_erro
        end.

      值得优化:只在最底层用try catch把所有的错误都放到这里统一处理。

  • 相关阅读:
    使用Eclipse 创建Spring Boot项目
    springMVC中文乱码问题
    Java POI Excel 导入导出
    springMVC + quartz实现定时器(任务调度器)
    spring配置Converter、Formatter日期转换器
    springMVC+springJDBC+Msql注解模式
    基于JavaScript封装的Ajax工具类
    H5音乐播放器
    JavaWeb+MySql分页封装
    JS如何判断是否为ie浏览器的方法(包括IE10、IE11在内)
  • 原文地址:https://www.cnblogs.com/zhongwencool/p/try_catch.html
Copyright © 2011-2022 走看看