2017-01-14 5 views
1

Как использовать хвостовую рекурсию в Erlang, чтобы сказать, что у меня есть списки [[1], [2], [3], [3,2] ], и я хотел бы вывести список [[1], [1], [1], [2]], где каждый список в списке вывода представляет количество элементов (ов) для каждого списка в списке ввода?Рекурсия хвоста Erlang для нахождения количества элементов в каждом списке списка входных данных

Я новичок в функциональном программировании.

Благодаря

+0

Показать код, который вы пробовали. –

ответ

1

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

List = [[1], [2], [3], [3,2]], 
Result = lists:map(fun(X) -> [length(X)] end, List), 
Result = [[length(X)] || X <- List], 

Обычный и прямое рекурсивное решение этой проблемы

lengths_not_tail_recursive([]) -> []; % stop condition 
lengths_not_tail_recursive([H|T]) -> [[length(H)]|lengths_not_tail_recursive(T)]. 

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

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

lengths_tail_recursive([],Acc) -> lists:reverse(Acc); % stop condition 
% the result needs to be reverse due to the way the accumulator is built at each step 
lengths_tail_recursive([H|T],Acc) -> lengths_tail_recursive(T,[[length(H)]|Acc]). 

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

lengths(L) -> lengths_tail_recursive(L,[]). 

Примечания: рекурсивное решение хвоста использует 2 библиотечных функции: длина/1 и списки: reverse/1. Я предлагаю вам написать их хвостом рекурсивным способом.