I've written a validation function for Erlyweb. First I'll tell you how it works and then, perhaps, more thoughts on its internals.Create a form with four fields:- login- password- pasword_repeat- emailThis is a pretty standard registration form. Naturally we'd have to validate input coming from this form:- login has to be 4-16 symbols in length- password has to be 4-16 symbols in length- password has to be the same as password_repeat- email has to be a valid email addressErlyweb's validation functions cant cope with this. My function can :)Suppose you have a function called process_signup, which accepts the yaws_arg record. Then the validation will look like so:process_signup(A) -> F = fun(A, Field) -> {ok, Val} = yaws_api:postvar(A, Field), L = string:len(Val), if L < 4 orelse L > 16 -> {Field, length}; true -> {} end end, EmailCheck = fun(Args, Field2) -> {ok, Email} = yaws_api:postvar(Args, Field2), Match = regexp:match(Email, "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]+"), Match /= nomatch end, %% magic is here: buktu_form:validate(A, [ {login, F}, {email, EmailCheck}, {password, [{'=', password_repeat}, F]} ]). If we don't input any field at all, we'll get back the following list:[{login,invalid_field}, {email,invalid_field}, {password,[{invalid_fields,[password,password_repeat]}, invalid_field]}] If we input values that don't match our criteria, we'll get:[{login,length}, {email,invalid_value}, {password,[{not_equal,password_repeat}, length]}] The callback function that you can pass can return the following: a tuple {FieldName, Error}true if the field is validated and false otherwise (then the validation function will return {FieldName, invalid_value}) any value Value which will be transformed into {FieldName, Value} if any of the fields in the rule don't exist or are empty, for each such rule the validation function will return:invalid_field if the field is compared against a value{invalid_fields, [field1, field2]} if the field is compared against another fieldIf you need to bind several rules to a field, pass a list of rules. If you just need to check if a field exists, pass in a tuple containing the field's name:Does the field exist?{field_name} Compare a field field_name to field field2_name (you can use '=', '/=', '<', '=<', '>', '>=' ){field_name, {'=', field2_name}}Compare a field to any value: {field_name, {'=', Value}}Use a callback function (function/2, first parameter is yaws_arg, the second is the field's name). The function can be a lambda or any function of any module in the form of module:function/2 or {module, function}{field_name, F}Use a callback function with an additional value (function/3,first parameter is yaws_arg, the second is the field's name, the third is the value). The function can be a lambda or any function of any module in the form of module:function/3 or {module, function}{field_name, {F, Value}}The validation function returns a proplist:[{FieldName(), Errors()}]whereFieldName() = atom() Errors() = Error() | [Error()] Error() = user_defined_values | absent | invalid_value | invalid_field | {invalid_fields, [FieldName(), FieldName()]} | ComparisonError() ComparisonError() = {not_equal, value_or_field} | {equal, value_or_field} | {not_greater, value_or_field} | {not_less, value_or_field} | {not_greater_or_equal, value_or_field} | {not_less_or_equal, value_or_field} |