【问题标题】:In a sequence of Erlang matches, how do I tell which one of them has failed?在一系列 Erlang 匹配中,我如何判断其中哪一个失败了?
【发布时间】:2021-04-18 22:24:18
【问题描述】:

考虑以下 sn-p:

do_stuff() ->
    % assume each of BoundVarI is bound here
    BoundVar1 = term1(),
    BoundVar2 = term2(),
    % ...
    BoundVarN = termN(),
    ok.

do_stuff_wrapper() ->
    do_stuff().

在包装函数(do_stuff_wrapper/0)中,我如何准确地确定哪一个匹配失败了?为了清楚起见,我不是在寻找一种方法来告诉它只是失败了,可能是通过生成和监视一个进程,而是一种方法来告诉 哪个比赛导致失败。我考虑的一种方法是只从错误元组中提取行号,但我觉得这会极大地损害可维护性。

【问题讨论】:

    标签: exception erlang pattern-matching


    【解决方案1】:

    您可以尝试以下方式:

    ScopeRef = make_ref(), %% To make sure to catch only errors in this scope
    try
      {_, BoundVar1} = {{ScopeRef, term1}, term1()},
      {_, BoundVar2} = {{ScopeRef, term2}, term2()},
      {_, BoundVarN} = {{ScopeRef, termN}, termN()},
      %% ^ Consider turning this into a lists:foreach/recursion
      ok
    catch %% First error stops execution
      error:{badmatch, {{ScopeRef, FailedFunName}, _FailedTerm}} -> {error, {nomatch, FailedFunName}}
    end.
    

    或者,如果你想检查每一个

    BoundTerms = [BoundVar1, BoundVar2, BoundVarN],
    AssertFuns = [fun term1/0, fun term2/0, fun termN/0],
    FailedTerms = lists:reverse(lists:foldl(fun({BoundVar, AssertFun} = Pair, Acc) ->
      case AssertFun() of
        BoundVar -> Acc;
        _ -> [Pair | Acc]
      end
    end, [], lists:zip(BoundTerms, AssertFuns)),
    case FailedTerms of
      [] -> ok;
      _ -> exit({assert_failed, FailedTerms})
    end.
    

    根据实际问题,我会选择其中一个(或两者都不选),但这些示例显示了您可以调整的不同方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 2011-05-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多