[erlang-questions] How do I elegantly check many conditions?
Richard O'Keefe
ok@REDACTED
Mon Mar 23 04:13:35 CET 2009
On 21 Mar 2009, at 2:20 am, ryeguy wrote:
> So when a user sends a request to register an account, they send their
> username, password, email, and other info. The registration function
> must verify all of their data. An example would be:
>
> - verify email not in use
> - verify username not in use
> - verify username is alphanumeric
> - verify all fields are above X characters long
> - verify all fields are less than Y characters long
>
> Now I don't want to have a 5 level deep if or case statement, but what
> other options do I have?
For concreteness, let's suppose we have
email_is_available(Info) -> ok | {no,Reason}
user_syntax_ok(Info) -> ok | {no,Reason}
user_is_available(Info) -> ok | {no,Reason}
all_fields_long_enough(Info) -> ok | {no,Reason}
all_fields_short_enough(Info) -> ok | {no,Reason}
I'm assuming here that
(a) the field size and syntax checks should be done first,
as they just involve the data to hand
(b) the availability checks should only be done with verified data
(c) when a check fails you want the reason.
In short, we want to compose checkers. So let's try that.
compose_check(F1, F2) ->
fun (Info) ->
case F1(Info)
of ok -> F2(Info)
; Failure -> Failure
end
end.
Now we can do
compose_check_list(Check_Funs) ->
lists:foldl(fun compose_check/2, fun (_) -> ok end, Check_Funs).
and
compose_check_list([
fun all_fields_long_enough/1,
fun all_fields_short_enough/1,
fun user_syntax_ok/1,
fun email_is_ available/1,
fun user_is_available/1
])(Info)
Or we can avoid creating the intermediate functions and write
check_all(_, []) -> ok;
check_all(Info, [F|Fs]) ->
case F(Info)
of ok -> check_all(Info, Fs)
; Failure -> Failure
end.
...
check_all(Info, [
fun all_fields_long_enough/1,
fun all_fields_short_enough/1,
fun user_syntax_ok/1,
fun email_is_available/1,
fun user_is_available/1])
Or you could arrange your checkers to either return ok or
to throw {check_failed,Reason}, and do
try
all_fields_long_enough(Info),
all_fields_short_enough(Info),
user_syntax_ok(Info),
email_is_available(Info),
user_is_available(Info)
catch
throw:{check_failed,Reason} ->
{no,Reason}
end
More information about the erlang-questions
mailing list