在一系列 Erlang 匹配中,我如何判断其中一个失败了?

问题描述

考虑以下片段:

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) 中,我究竟如何确定哪一个匹配失败了?明确地说,我不是在寻找一种方法来告诉它刚刚失败了,可能是通过生成和监视一个进程,而是一种方法来告诉哪个比赛已导致失败。我考虑的一种方法是只从错误元组提取行号,但我觉得这会极大地损害可维护性。

解决方法

您可以尝试以下方式:

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.

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