Начинающий вопрос - нужно ли использовать ifs или короткие функции при программировании erlang? - PullRequest
4 голосов
/ 08 марта 2011

Я начал серьезно изучать книгу по программированию на языке Эрланг, и у меня есть вопрос. Подходящий подход к Erlang ниже? Это (изменено для краткости (без сообщения о выходе) с удалением регистрации после базовой проверки) решение проблемы с кольцом из ch4. Процессы завершаются после того, как они передали сообщение предполагаемое количество раз; Первый процесс ожидает, пока последнее сообщение достигнет его, и завершает работу.

Помимо общей критики стиля и содержания, подскажите, пожалуйста, правильно ли писать специальные 1-2-строчные функции, подобные этой, или следует использовать if-s, case-s и т. Д.

start_ring( 0, _, _ ) -> {error, badarg};
start_ring( _, 0, _ ) -> {error, badarg};
start_ring( M, N, Message ) -> 
    spawn( ring, run_ring, [M, N, Message, 0] ).

% last process that connects the ring 
run_ring( M, 1, Message, Pid ) when is_pid(Pid) -> 
    loop_ring( M, Message, Pid, false );

% process in the middle
run_ring( M, N, Message, Pid ) when is_pid(Pid) ->
    loop_ring( M, Message, spawn( ring, run_ring, [M, N-1, Message, Pid] ), false );

% first process - special case for one process
run_ring( M, 1, Message, _ ) -> 
    loop_ring( M, self() ! Message, self(), true );

% first process 
run_ring( M, N, Message, _ ) -> 
    NextPid = spawn( ring, run_ring, [M, N-1, Message, self()] ),
    loop_ring( M, NextPid ! Message, NextPid, true ).

loop_ring( 0, _, _, _ ) -> ok;

loop_ring( 1, Message, Next, true ) -> ok;

loop_ring( M, Message, Next, IsMaster ) ->
    receive 
        Message -> loop_ring( M - 1, Next ! Message, Next, IsMaster )
    end.

Ответы [ 2 ]

7 голосов
/ 08 марта 2011

Я думаю, что ваш стиль очень хорош и лаконичен!Хорошая работа!

Несколько комментариев (дело личного вкуса):

  • Стартовое кольцо можно переписать так:

    start_ring( M, N, Message ) when M < N, N > 0, M > 0 -> 
       spawn( ring, run_ring, [M, N, Message, 0] ).
    

    Это будетсбой с ошибкой function_clause при неправильном использовании.При работе с возвратами ошибок есть хорошая привычка: если пользователь может сделать что-то разумное с ошибкой, верните, например, {error, Reason}, иначе просто вылетите.Я думаю, что в этом случае безопасно просто аварийно завершить работу, потому что любой другой ввод будет ошибкой в ​​программе.

  • run_ring/4 + loop_ring/4: я не люблюиспользовать разрывы строк между функциями с несколькими предложениями.Это затрудняет понимание того, где функция начинается и заканчивается.Комментарии могут быть помещены внутри тела предложения, а не снаружи.Теперь стало намного проще определять заголовки функций (и рассматривать функцию как единое целое):

    run_ring(M, 1, Message, Pid) when is_pid(Pid) ->
        % last process that connects the ring
        loop_ring(M, Message, Pid, false);
    run_ring(M, N, Message, Pid) when is_pid(Pid) ->
        % process in the middle
        loop_ring(M, Message, spawn(ring, run_ring, [M, N-1, Message, Pid]), false);
    run_ring(M, 1, Message, _) ->
        % first process - special case for one process
        loop_ring(M, self() ! Message, self(), true);
    run_ring(M, N, Message, _) ->
        % first process
        NextPid = spawn(ring, run_ring, [M, N-1, Message, self()]),
        loop_ring(M, NextPid ! Message, NextPid, true).
    
  • Мне лично не нравятся пробелы в скобках (как я уже сказал, личный вкус)).:-) Делает код более «пушистым».

  • Используйте spawn_link/3 вместо spawn/3, если только вы не знаете, что вам это не нужно.Это значительно упрощает обнаружение ошибок и т. Д. При разработке программы.

  • Второе предложение loop_ring/4 выдает предупреждения компилятора.Вместо этого используйте _Message и _Next (используйте их также для первого предложения, это бонусная документация!)

3 голосов
/ 08 марта 2011

Согласно рекомендациям Erlang , следует избегать вложений if и case более двух раз:

Вложенный код - это код, содержащий регистр / if / receiveзаявления в другом случае / если / получить заявления.Писать глубоко вложенный код - плохой стиль программирования - он имеет тенденцию перемещаться по странице вправо и вскоре становится нечитаемым.Попробуйте ограничить большую часть вашего кода максимум двумя уровнями отступа.Это может быть достигнуто путем деления кода на более короткие функции.

Кроме того, я полагаю, что это вопрос вкуса - использовать if/case или простое сопоставление с образцом.Лично я предпочитаю использовать сопоставление с образцом, а не с делами или случаями.Итак, вы делаете это правильно, если вы спросите меня.

Что касается if и case, обычно вы можете переписать первое в последнее.Кто-то говорит:

«всегда используйте регистр, если конструкция if как бы неработоспособна».

Ну, две конструкции работают совершенно по-разному.Выражение, вычисленное в конструкции if, является защитным и имеет множество ограничений - из-за того, что вы не можете иметь побочных эффектов для защиты, будучи оцененными независимо от выбранной ветви -.Конструкция case не имеет этого «ограничения».Здесь можно использовать любое выражение, результат которого будет сопоставляться с образцами, образующими регистр.

Возможный дубликат:

Стиль Erlang - регистр и сопоставление шаблонов функций

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