Оператор случая Erlang

У меня есть следующий код Erlang, и он выдает следующее предупреждение, когда я пытаюсь его скомпилировать, но это имеет смысл. функции нужны два аргумента, но мне нужно, чтобы шаблон соответствовал «всему остальному», а не x, y или z.

-module(crop).
-export([fall_velocity/2]).

fall_velocity(P, D) when D >= 0 ->
case P of
x -> math:sqrt(2 * 9.8 * D);
y -> math:sqrt(2 * 1.6 * D);
z -> math:sqrt(2 * 3.71 * D);
(_)-> io:format("no match:~p~n")
end.

crop.erl:9: Warning: wrong number of arguments in format call. 

Я пробовал анонимную переменную после io:format, но все равно не доволен.


person Tharanga Abeyseela    schedule 13.01.2014    source источник


Ответы (2)


В формате, который вы используете ~p. Это означает -- распечатать значение. Поэтому вы должны указать, какое значение печатать.

последняя строка регистра должна быть

_ -> io:format("no match ~p~n",[P])

Кроме того, io:format возвращает «ok». Поэтому, если P не является x, y или z, ваша функция вернет «ok» вместо числового значения. Я бы предложил вернуть помеченное значение для разделения правильных и ошибочных результатов. Вроде

fall_velocity(P, D) when D >= 0 ->
case P of
x -> {ok,math:sqrt(2 * 9.8 * D)};
y -> {ok,math:sqrt(2 * 1.6 * D)};
z -> {ok,math:sqrt(2 * 3.71 * D)};
Otherwise-> io:format("no match:~p~n",[Otherwise]),
            {error, "coordinate is not x y or z"}
end.
person Odobenus Rosmarus    schedule 13.01.2014
comment
Я бы выдал исключение или, может быть, просто не проверял ничего, кроме x, y, z. Erlang явно терпит неудачу, не нужно переусердствовать. - person Berzemus; 13.01.2014
comment
правильно. Но если не проверять, то можно получить ошибку где-то намного позже вызова функции. {ok,R} = fall_velocity(A,B) раньше могло указывать на ошибку. - person Odobenus Rosmarus; 13.01.2014
comment
На самом деле, это зависит от того, кто вызывает функцию. Если функция является частью API, помеченные значения действительно приветствуются. Но если функция является внутренней частью глубоко внутри вашей кодовой базы, вы в конечном итоге будете иметь операторы case повсюду, постоянно проверяя ошибки в своем собственном коде, что является ненужной проблемой. Просто позвольте ему потерпеть неудачу. - person Berzemus; 13.01.2014
comment
Это одна из тех вещей, которые легко проверить, поэтому они решили добавить для нее проверку предупреждений. Это всего лишь предупреждение, поэтому, если вы решите игнорировать его, вы получите сообщение об ошибке при запуске кода. - person rvirding; 13.01.2014

Чтобы сделать комментарии к другому ответу явными, я бы написал эту функцию следующим образом:

-module(crop).
-export([fall_velocity/2]).

fall_velocity(P, D) when D >= 0 ->
    case P of
        x -> math:sqrt(2 * 9.8 * D);
        y -> math:sqrt(2 * 1.6 * D);
        z -> math:sqrt(2 * 3.71 * D)
    end.

То есть не обрабатывайте неверный аргумент в выражении case. Если кто-то передаст foo в качестве аргумента, вы получите сообщение об ошибке {case_clause, foo} вместе с трассировкой стека, указывающей на эту функцию и вызывающую ее функцию. Это также означает, что эта функция не может передавать неправильные значения в остальную часть кода в результате вызова с неправильными аргументами.

Возврат {ok, Result} | {error, Error}, как и в другом ответе, одинаково действителен. Вам нужно будет выбрать вариант, который лучше всего подходит для вашего случая.

person legoscia    schedule 13.01.2014