Как мне элегантно проверить многие условия в Эрланге? - PullRequest
13 голосов
/ 20 марта 2009

Поэтому, когда пользователь отправляет запрос на регистрацию учетной записи, он отправляет свое имя пользователя, пароль, электронную почту и другую информацию. Функция регистрации должна проверять все свои данные. Примером может быть:

  • подтверждение того, что электронная почта не используется
  • подтвердить, что имя пользователя не используется
  • подтвердить, что имя пользователя буквенно-цифровое
  • убедитесь, что все поля больше X символов
  • проверить, что длина всех полей меньше Y символов

Теперь я не хочу иметь 5-уровневую инструкцию if или case, но какие еще есть варианты? Разделение его на отдельные функции звучит как хорошая идея, но тогда мне просто нужно проверить возвращаемое значение функций в каком-то условном выражении, и это вернулось к исходной проблеме.

Я мог бы разделить их на функции и затем вызвать оператор if со всеми условными операциями OR вместе, но это не дало бы мне того, чего я хочу, потому что мне нужно было бы сообщить пользователю конкретную ошибку, если был один.

Как справиться с подобной ситуацией в эрланге? Есть ли эквивалент оператора возврата или это должна быть последняя исполняемая строка в функции, чтобы быть возвращаемым значением?

Ответы [ 3 ]

32 голосов
/ 21 марта 2009

Одно из предложений Джо Армстронга: код примера успеха программы отделен от обработки ошибок. Вы можете сделать это таким образом

create_user(Email, UserName, Password) ->
  try
    ok = new_email(Email),
    ok = valid_user_name(UserName),
    ok = new_user(UserName),
    ok = strong_password(Password),
    ...
    _create_user(Email, UserName, Password)
  catch
    error:{badmatch, email_in_use} -> do_something();
    error:{badmatch, invalid_user_name} -> do_something();
    error:{badmatch, user_exists} -> do_something();
    error:{badmatch, weak_password} -> do_something();
    ...
  end.

обратите внимание, что вы можете делать все ошибки, ловящие из функции create_user, что лучше.

create_user(Email, UserName, Password) ->
    ok = new_email(Email),
    ok = valid_user_name(UserName),
    ok = new_user(UserName),
    ok = strong_password(Password),
    ...
    _create_user(Email, UserName, Password).

main() ->
  try
    ...
    some_function_where_create_user_is_called(),
    ...
  catch
    ...
    error:{badmatch, email_in_use} -> do_something();
    error:{badmatch, invalid_user_name} -> do_something();
    error:{badmatch, user_exists} -> do_something();
    error:{badmatch, weak_password} -> do_something();
    ...
  end.

Сопоставление с образцом - одна из самых крутых вещей в Эрланге. Обратите внимание, что вы можете включить ваш тег в ошибку badmatch

{my_tag, ok} = {my_tag, my_call(X)}

и пользовательские данные тоже

{my_tag, ok, X} = {my_tag, my_call(X), X}

Если исключение достаточно быстро для вас, зависит от ваших ожиданий. Скорость на моем 2,2 ГГц Core2 Duo Intel: около 2 миллионов исключений в секунду (0,47 мкс) по сравнению с 6 миллионами успешных (внешних) вызовов функций (0,146 мкс) - можно предположить, что обработка исключений занимает около 0,32 мкс. В нативном коде это 6,8 против 47 миллионов в секунду, а обработка может занять около 0,125us. Может потребоваться дополнительная плата за конструкцию try-catch, которая составляет около 5-10% от вызова функции success как в собственном, так и в байт-коде.

4 голосов
/ 20 марта 2009
User = get_user(),

Check_email=fun(User) -> not is_valid_email(User#user.email) end,
Check_username=fun(User) -> is_invalid_username(User#user.name) end,

case lists:any(fun(Checking_function) -> Checking_function(User) end, 
[Check_email, Check_username, ... ]) of
 true -> % we have problem in some field
   do_panic();
 false -> % every check was fine
   do_action()
 end

Так что это уже не 5 уровень глубины. Для реальной программы, я думаю, вы должны использовать lists: foldl для накопления сообщения об ошибке из каждой функции проверки. Потому что сейчас все просто говорит «все хорошо» или «какая-то проблема».

Обратите внимание, что таким образом добавить или удалить условие проверки не имеет большого значения

А для "Есть ли эквивалент оператора return ..." - посмотрите на оператор try catch throw, в этом случае throw действует как return.

0 голосов
/ 05 мая 2013

Может быть, вам понадобится

receive
    message1 -> code1;
    message2 -> code2;
    ...
end.

Но, конечно, будут методы spawn ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...