Reputation: 33
Consider the following snippet:
do_stuff() ->
% assume each of BoundVarI is bound here
BoundVar1 = term1(),
BoundVar2 = term2(),
% ...
BoundVarN = termN(),
ok.
do_stuff_wrapper() ->
do_stuff().
In the wrapper function (do_stuff_wrapper/0
), how exactly do I determine which one of the matches has failed? Just to be clear, I'm not looking for a way to tell that it has just failed, possibly by spawning and monitoring a process, but a way to tell which of the matches has caused to fail. One way I considered would be to just extract the line number from the error tuple, but I feel like that hurts maintainability a lot.
Upvotes: 2
Views: 58
Reputation: 3509
You could try something along the lines of:
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.
or, if you want to check every one
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.
Depending on the actual problem, I'd choose one or the other (or neither), but these examples show different approaches that you can tweak.
Upvotes: 3