Подтвердить что ты не робот

Есть ли идиоматический способ упорядочения аргументов функции в Erlang?

Похоже, что он несовместим в модуле списков. Например, split имеет номер в качестве первого аргумента, а список - второй, но подсписок имеет список как первый аргумент, а len - второй аргумент.

4b9b3361

Ответ 1

Хорошо, небольшая история, как я помню, и некоторые принципы, лежащие в основе моего стиля.

Как сказал христианин, библиотеки эволюционировали и имели тенденцию получать аргумент и чувствовать себя от импульсов, которые мы получили именно тогда. Так, например, причина, почему элемент /setelement имеет порядок аргументов, который они делают, состоит в том, что он соответствует предикату arg/3 в Prolog; логично, но не сейчас. Зачастую у нас была бы работа над первым, но, к сожалению, не всегда. Это часто хороший выбор, поскольку он позволяет добавлять "необязательные" аргументы в конец; например, строка: substr/2/3. Функции с вещью в качестве последнего аргумента часто зависели от функциональных языков с currying, например Haskell, где очень легко использовать currying и частичную оценку для создания определенных функций, которые затем могут быть применены к предмету. Это очень заметно в функциях более высокого порядка в списках.

Единственное влияние, которое у нас не было, было в мире ОО.: -)

Обычно нам, по крайней мере, удалось быть согласованным внутри модуля, но не всегда. См. Списки снова. Мы старались иметь некоторую согласованность, поэтому порядок аргументов в функциях более высокого порядка в dict/sets соответствует характеристикам соответствующих функций в списках.

Проблема также усугублялась тем, что мы, особенно меня, имели довольно бесцеремонное отношение к библиотекам. Я просто не рассматривал их как точку продажи языка, поэтому я не беспокоился об этом. "Если вам нужна библиотека, которая что-то делает, тогда вы просто пишете ее", был моим девизом. Это означало, что мои библиотеки были структурированы, но не всегда с одинаковой структурой.:-) Вот как многие из начальных библиотек появились.

Это, конечно, создает ненужную путаницу и нарушает закон наименьшего удивления, но мы ничего не можем с этим поделать. Любые предложения по пересмотру модулей всегда встречались с громким "нет".

Мой собственный стиль обычно структурирован, хотя я не знаю, соответствует ли он любым письменным рекомендациям или стандартам.

Обычно у меня есть предмет или вещи, над которыми я работаю, в качестве первых аргументов или, по крайней мере, очень близко к началу; порядок зависит от того, что лучше. Если существует глобальное состояние, связанное через весь модуль, который обычно существует, он помещается в качестве последнего аргумента и дает очень описательное имя, такое как St0, St1,... (я принадлежу к церкви с короткими именами переменных). Аргументы, связанные цепью через функции (как входные, так и выходные), я пытаюсь сохранить тот же порядок аргументов, что и порядок возврата. Это значительно упрощает просмотр структуры кода. Кроме того, я пытаюсь объединить аргументы, которые принадлежат друг другу. Кроме того, где это возможно, я пытаюсь сохранить тот же порядок аргументов во всем модуле.

Ничто из этого не является очень революционным, но я нахожу, что если вы придерживаетесь последовательного стиля, то об этом меньше всего беспокоиться, и это заставляет ваш код чувствовать себя лучше и, как правило, более читабельным. Кроме того, я действительно буду переписывать код, если порядок аргументов кажется неправильным.

Небольшой пример, который может помочь:

fubar({f,A0,B0}, Arg2, Ch0, Arg4, St0) ->
    {A1,Ch1,St1} = foo(A0, Arg2, Ch0, St0),
    {B1,Ch2,St2} = bar(B0, Arg4, Ch1, St1),
    Res = baz(A1, B1),
    {Res,Ch2,St2}.

Здесь Ch - локальная цепочечная переменная, а St - более глобальное состояние. Проверьте код на github для LFE, особенно компилятор, если вы хотите более длинный пример.

Это стало намного дольше, чем должно было быть, извините.

P.S. Я использовал слово "вещь" вместо объекта, чтобы избежать путаницы в отношении того, что я говорил.

Ответ 2

Нет, нет неизмененной идиомы в том смысле, что вы имеете в виду.

Однако есть некоторые полезные релевантные подсказки, которые применяются, особенно когда вы собираетесь делать рекурсивные вызовы. Например, сохранение любых аргументов останется неизменным во время хвостовых вызовов в том же порядке/позиции в списке аргументов, что позволяет виртуальной машине сделать некоторые очень приятные оптимизации.