суббота, 12 ноября 2011 г.

Определение места badmatch при вызове одинаковых функций

Итак, допустим, что у вас есть вот такой код:

sometimes_not_ok(42) ->
  not_ok;
sometimes_not_ok(_) ->
  ok.
test() ->
  ok = sometimes_not_ok(13),
  ok = sometimes_not_ok(42).
Функция sometimes_not_ok/1 возможно говорит с бд, или ещё чего-нибудь такого и может выбрасывать исключения/возвращать значения, которые никак не характеризуют аргументы, переданные ей.

У нас есть 2 пути, как сделать так, чтобы мы знали, в каком месте случился фейл. Первый из них заключается в том, чтобы обернуть всё в case'ы:


case sometimes_not_ok(13) of
  ok ->
    case sometimes_not_ok(42) of
      ok ->
        continue_here;
      not_ok ->
        not_ok_processing
    end;
  not_ok ->
    not_ok_processing
end.
Однако согласитесь, код при этом станет выглядеть ужасно. А если вам нужно будет поменять две строчки местами? А если у вас сотня таких вызовов? Да и это какое-то дефендное программирование выходит, у эрланга несколько другая концепция.

Второй же наш вариант, использовать try/catch:

try
  ok = sometimes_not_ok(13),
  ok = sometimes_not_ok(42)
catch
  error:{badmatch, not_ok} ->
    not_ok_happened
end.
Уже намного лучше. Первоначальный код виден, его можно легко поправить, нет кучи вложенных условий. Однако... когда произойдёт {badmatch, not_ok}, мы не будем знать, на какой строке он произошёл, там где мы передали 18, или же 42? А вот нам позарез нужно выполнять там какие-то действия, если не ок.

Ну и мне пришло в голову, что можно просто обернуть вызов функции в tuple. Вот так:

try
  {_, ok} = {first, sometimes_not_ok(13)},
  {_, ok} = {second, sometimes_not_ok(42)}
catch
  error:{badmatch, {first, not_ok}} ->
    not_ok_happened_first;
  error:{badmatch, {second, not_ok}} ->
    not_ok_happened_second
end.
И тогда мы с лёгкостью можем определить, в каком из мест у нас badmatch. Конечно, внешний вид кода стал немножечко не таким красивым, но ведь согласитесь, так намного лучше, чем с кучей case'ов?

Может быть, конечно, мой «способ» всем давно известен, тогда уж ладно. Но мои знания всё равно растут :).





3 коммент.:

  1. АнонимныйNov 12, 2011 01:44 AM

    Какая у тебя интересная работа. Где работаешь?

    ОтветитьУдалить
  2. Нигде, я студент. Однако, есть одно дело :)
    Напишу чуть позже об этом.

    ОтветитьУдалить
  3. АнонимныйNov 13, 2011 05:21 AM

    Это охуенно, бро. Я пока на пыхе дела делаю, даже до джанги не дорос

    ОтветитьУдалить