Какое ваше соглашение об именах для вспомогательных функций?

В функциональном программировании часто важно оптимизировать любой "циклический" код, чтобы он был рекурсивным. Рекурсивные алгоритмы хвоста обычно разделяются между двумя функциями, однако - одна из которых устанавливает базовый регистр, а другой - реализует фактический цикл. Хорошим (хотя и академическим) примером будет обратная функция.

reverse :: [a] -> [a]
reverse = reverse_helper []

reverse_helper :: [a] -> [a] -> [a]
reverse_helper result [] = result
reverse_helper result (x:xs) = reverse_helper (x:result) xs

"reverse_helper" на самом деле не очень хорошее описательное имя. Однако "reverse_recursive_part" просто неудобно.

Какое соглашение об именах вы использовали бы для вспомогательных функций, подобных этому?

Ответ 1

Я обычно добавляю "_recurse" до конца. Итак, "reverse_recurse". Не знаю, откуда у меня это получилось. Мне нравится оставить функцию базового блока простой, как у вас в вашем примере. Он имеет тенденцию быть "общедоступной" функцией, и тот факт, что он использует вспомогательную функцию для выполнения итерации, не имеет отношения к вызывающему. В javascript я иногда зашел так далеко, чтобы скрыть итеративную функцию через закрытие, чтобы сделать ее действительно прозрачной, ее нельзя вызывать напрямую.

Ответ 2

Вы можете вызвать вспомогательную функцию, что угодно, и это не имеет значения, если вы не помещаете вспомогательную функцию в "глобальное" пространство имен. Простое добавление "простого" кажется обычной практикой.:) Например, в Haskell,

reverse :: [a] -> [a]
reverse = reverse' []
    where reverse' :: [a] -> [a] -> [a]
          reverse' result [] = result
          reverse' result (x:xs) = reverse' (x:result) xs

Ответ 3

Я всегда использую do_, например "do_compute" с "compute". Я нахожу это довольно описательным, так как он фактически является частью функции, выполняющей действие, тогда как "вычисляемый", который вызывается, должен иметь простое описательное имя для внешнего мира.

Ответ 4

Я согласен с ShreevatsaR, если вы не делаете вспомогательную функцию верхнего уровня (или, что еще хуже, помещаете ее в список экспорта), чем это не имеет значения, каково ее имя. Я обычно вызываю вспомогательные функции f и g.

reverse :: [a] -> [a]
reverse = f []
  where
    f ys []     = xs
    f ys (x:xs) = f (x:ys) xs

Я просто использую эту схему именования для небольших функций (иначе я не знаю, что означает f). Опять же, зачем вам писать большие функции?

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

reverseAccumulator

Как Haskell zip и zipWith. Но я бы не назвал эти "вспомогательные" функции, zipWith является всего лишь общей функцией, а zip является реализацией по умолчанию (вероятно, тот, который больше всего использовался).

Ответ 5

Я также согласен с ShreevatsaR, в этом примере я бы сделал помощником частную функцию.

В других случаях, когда мне нужно, чтобы вспомогательные функции были видимыми во всем модуле, но не экспортировались, я предпочитаю префиксные функции с помощью "_". Конечно, есть явный экспортный отчет, но во время разработки я стараюсь экспортировать все функции для облегчения интерактивного исследования, например. в ghci. Позже я добавляю список экспортируемых функций, а нижний байт упрощает запоминание того, была ли я назначена функция локальной или нет.

Ответ 6

Я использую aux или foo_aux (для основной функции foo) и вставляю определение, чтобы оно не выглядело внешне.

Ответ 7

настроить и выполнить

Пример:

function whateverSetup() { ... }
function whateverExecute() { ... }