Рекурсия - важная часть Эрланг. Сначала давайте посмотрим, как мы можем реализовать простую рекурсию, реализуя факториальную программу.
-module(helloworld).
-export([fac/1,start/0]).
fac(N) when N == 0 -> 1;
fac(N) when N > 0 -> N*fac(N-1).
start() ->
X = fac(4),
io:fwrite("~w",[X]).
Необходимо отметить следующее:
- Сначала мы определяем функцию, называемую fac (N)
- Мы можем определить рекурсивную функцию, вызвав рекурсивно функцию fac (N)
Практический подход к рекурсии
В этом разделе мы подробно рассмотрим различные типы рекурсий и его использование в Erlang.
Длина рекурсии
Более практичный подход к рекурсии можно увидеть с помощью простого примера, который используется для определения длины списка. Список может иметь несколько значений, например [1,2,3,4]. Давайте используем рекурсию, чтобы узнать, как мы можем получить длину списка.
-module(helloworld).
-export([len/1,start/0]).
len([]) -> 0;
len([_|T]) -> 1 + len(T).
start() ->
X = [1,2,3,4],
Y = len(X),
io:fwrite("~w",[Y]).
Необходимо отметить следующее:
- Первая функция len ([]) используется для специального условия случая, если список пуст.
- [H | T] , шаблон для сопоставления списков одного или более элементов, в виде списка длины один будет определяться как [Х | []] и список длины два будет определяться как [X | [Y | [ ]]] . Обратите внимание, что второй элемент - это сам список. Это означает, что нам нужно только считать первый, и функция может называть себя вторым элементом. Учитывая, что каждое значение в списке считается длиной 1.
Хвостовая рекурсия
Чтобы понять, как работает хвостовая рекурсия, давайте разобраться, как работает следующий код в предыдущем разделе.
len([]) -> 0;
len([_|T]) -> 1 + len(T).
Ответ на 1 + len (Rest) требует ответа len (Rest), который нужно найти. Сама функция len (Rest) требовала результата другого вызова функции. Добавления будут складываться до тех пор, пока не будет найден последний, и только тогда будет рассчитан конечный результат.
Рекурсия хвоста направлена на то, чтобы устранить эту сложность операций, уменьшив их по мере их возникновения.
Чтобы достичь этого, нам нужно будет содержать дополнительную временную переменную в качестве параметра в нашей функции. Вышеупомянутая временная переменная иногда называется аккумулятором и выступает в качестве места для хранения результатов наших вычислений по мере их возникновения, чтобы ограничить рост наших вызовов.
-module(helloworld).
-export([tail_len/1,tail_len/2,start/0]).
tail_len(L) -> tail_len(L,0).
tail_len([], Acc) -> Acc;
tail_len([_|T], Acc) -> tail_len(T,Acc+1).
start() ->
X = [1,2,3,4],
Y = tail_len(X),
io:fwrite("~w",[Y]).
0 комментариев