Каково ваше соглашение об именах для вспомогательных функций? - PullRequest
10 голосов
/ 06 января 2009

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

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» просто неловко.

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

Ответы [ 7 ]

22 голосов
/ 07 января 2009

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

reverse :: [a] -> [a]
reverse = reverse' []
    where reverse' :: [a] -> [a] -> [a]
          reverse' result [] = result
          reverse' result (x:xs) = reverse' (x:result) xs
6 голосов
/ 07 января 2009

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

5 голосов
/ 07 января 2009

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

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

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

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

reverseAccumulator

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

3 голосов
/ 07 января 2009

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

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

3 голосов
/ 07 января 2009

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

2 голосов
/ 07 января 2009

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

1 голос
/ 06 января 2009

настройка и выполнение

пример:

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