[erlang-questions] Idiomatically handling multiple validation checks

Jesper Louis Andersen <>
Tue Dec 6 14:42:45 CET 2016


On Tue, Dec 6, 2016 at 5:52 AM qp <> wrote:

> Hi, I am new to Erlang and wrote this code for validating that the Name,
> Action & Target atoms passed in to validRequest are all valid.
>
>
Another solution is this:

Let us start by assuming the presence of functions of this form:

-spec valid_name(Target) -> {name, Name} | {error, Reason}.
-spec valid_action(Target) -> {action, Name} | {error, Reason}.
-spec valid_request(Target) -> {request, Name} | {error, Reason}.

We would like to set up a verifier which either returns a context, or fails
with the errors present in that context:

-type context() :: #{ name := any(), action := any(), request := any(), _
=> _ }.

-spec verify(Target) -> {ok, context()} | {error, [Reason]}.

The context contains input-coerced, verified data and is represented as a
map in order to make it easier to users to process that context later on.

verify(Target) ->
    ErrorF = fun
                ({error, _}) -> true;
                (_) -> false
            end,
    case lists:partition(ErrorF, [valid_name(Target),
                                  valid_action(Target),
                                  valid_request(Target)]) of
        {OK, []} ->
            {ok, maps:from_list(OK)};
        {_, Errs} ->
            {error, Errs}
    end.

The function uses 'lists:partition/2' to split the errors away from the
valid outputs. Then we can simply match on the errors: if there are none,
we proceed with the context. If there are errors, return them all.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20161206/415d27cd/attachment.html>


More information about the erlang-questions mailing list