[erlang-questions] How do I elegantly check many conditions?

Anders Dahlin anders@REDACTED
Fri Mar 20 14:57:54 CET 2009



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? Splitting it into separate functions sounds
> like a good idea, but then I just have to check the return value of
> the functions in some sort of conditional and it's back to the
> original problem.
> 
> I could separate them into functions and then call an if statement
> with all of the conditionals OR'd together, but that wouldn't give me
> what I want because I need to be able to tell the user the specific
> error if there was one.
> 
> How does one handle this kind of situation in erlang?


Two alternatives that I've used. Both make it easy to extend the checks
without having to change a thing at the top level. I've also used
versions that updates the data at the same time and with more levels
than valid, invalid. Depending on the problem you may also want to
continue doing all checks and collecting the invalid stuff as you find
it so that everything that's not valid are returned at once.

/A


handle_input(Data) ->
    case validate(Data) of
	valid ->
	    foo();
	{invalid, Reason} ->
	    bar()
    end.


Alt1: Looping over funs

validate(InData) ->
    Validators = [fun validate_email/1,
		  fun validate_username/1],
    validate(Validators, InData).


validate([Validator| Validators], Data) ->
    case Validator(Data) of
	valid ->
	    validate(Validators, Data);
	{invalid, Reason} ->
	    {invalid, Reason}
    end;
validate([], _) ->
    valid.

validate_email(Data) ->
    valid.

validate_username(Data) ->
    valid.



Alt2: Looping over tags, used as first arg to validator/2

validate(Data) ->
    WhatToValidate = [email, username],
    validate(WhatToValidate, InData).


validate([Thing| Rest], Data) ->
    case validator(Thing, Data) of
	valid ->
	    validate(Rest, Data);
	{invalid, Reason} ->
	    {invalid, Reason}
    end;
validate([], _) ->
    valid.


validator(email, Data) ->
    valid;
validator(username, Data) ->
    valid.





More information about the erlang-questions mailing list