Сопоставление с образцом. Если вам нужно проверить пустой список в страже или if
или cond
, почти наверняка у вас есть структурная проблема с тем, как вы думаете об Erlang.
Это почти всегда проявляется в запутанном коде и странных крайних случаях, которые заставляют вас спрашивать себя, например, как проверить пустой список? не понимая, что на самом деле вы спрашиваете, как проверить наличие пустого списка в качестве процедурного условия? Это проклятие разумного функционального программирования.
Изменить: еще несколько объяснений и примеров.
Везде, где вы хотите ввести сопоставление с образцом, вы можете использовать что-то вроде case, или вы можете разбить все, что вы делаете, в отдельную функцию. Очень часто вы обнаруживаете семантическую двусмысленность, при которой вещи слишком тесно связаны, с одной стороны (вы выполняете другую работу, кроме получения сообщений в receive
), и слишком слабо, с другой стороны (вы занимаетесь во множестве произвольных процедурных проверок перед вызовом функции, когда действительно сопоставление параметров является естественным решением).
looper(V, ViewerSet) ->
receive
{From, set_value, V} ->
set_viewer_values(V, ViewerSet),
looper(V, ViewerSet);
% OtherStuff ->
% whatever else looper/2 does...
end.
set_viewer_values(V, []) ->
set_default_values(V);
set_viewer_values(V, ViewerSet) ->
% ... whatever the normal function definition is...
Куда бы вы ни отправляли изнутри вашего приема, это то, что должно выполнять фактическую работу, и это также место, где вы хотите выполнять сопоставление. Поскольку это в любом случае вызов функции, сопоставление здесь хорошо подходит и упрощает ваш код.
Если вы хотите сопоставить в самом looper/2
, это, безусловно, возможно. Я не знаю, что вы хотите делать, когда получаете пустой список, поэтому я кое-что придумаю, но вы можете делать все, что хотите:
looper(V, []) ->
looper(V, default_set());
looper(V, ViewerSet) ->
% As before, or whatever makes sense.
Вы даже можете решить, что когда у вас пустой набор, вам нужно действовать совершенно по-другому:
full_looper(V, []) ->
empty_looper(V);
full_looper(V, ViewerSet) ->
receive
{new_set, Set} ->
looper(V, Set);
{From, set_value, V} ->
set_viewer_values(V, ViewerSet),
looper(V, ViewerSet)
end.
empty_looper(V) ->
receive
{new_set, Set} ->
full_looper(V, Set);
{From, set_value, V} ->
set_viewer_values(V, default_set()),
empty_looper(V)
end.
Моя точка зрения выше заключается в том, что есть много способов справиться с ситуацией с пустым набором, не прибегая к произвольной процедурной проверке, и все они читаются легче, когда вы знаете, что делать (пока вы не привыкнете делать что-то таким образом, однако, это может показаться довольно странным). В качестве примечания: последний пример на самом деле создает конечный автомат - и уже есть модуль OTP, который действительно упрощает создание конечных автоматов. (Их тоже легко написать вручную в Erlang, но еще проще с модулем gen_fsm
.)
Попробуйте Регистр, чтобы проверить, когда список пуст а не рекурсия?
person
zxq9
schedule
02.11.2014