Понимание вызова функций и сопоставления с образцом

Прошел месяц с тех пор, как я начал изучать программирование на Эликсире, сегодня мне удалось написать код для получения последовательности Фибоначчи самостоятельно, без обращения к какой-либо документации или помощи моего учителя.
И это заняло всего 2 часа ;)
Позвольте мне провести вас через путешествие.
|› Последовательность Фибоначчи
Таким образом, последовательность Фибоначчи начинается с 0,1, а следующее число в последовательности является суммой двух предыдущих чисел. Образец "0,1,1,2,3,5,8,..."
|› Определение функций и элементов
Чтобы начать последовательность, мне нужно как минимум два целых числа, поэтому я начал со следующего.
defmodule Fibonacci do def fib(n) do fib(0, 1, [], n) end end

Здесь я определил функцию "fib(n)" с одной арностью "n", которая является входным значением от пользователя, что означает, что программа должна возвращать первое число "n" значений в последовательности Фибоначчи. Это также количество раз, которое должна произойти рекурсия для получения желаемого результата.
В теле вышеуказанной функции я назвал другую функцию "fib(0, 1, [], n)", которая еще не существует, и эта функция имеет 4 арности, и эта функция отличается от той, которую я определил ранее.
|› Сопоставление шаблонов и рекурсия
Теперь я определяю функцию "fib(prev, curr, acc, n)", которая также имеет 4 арности. когда я вызываю эту функцию в строке 3, значения в "fib(0, 1, [], n)" соответствуют образцу функции в строке 6, и эти значения будут скомпилированы в теле функции.
Здесь я также принимаю входное значение от пользователя "n = 5", полученное из функции в строке 2 "fib (n)".
defmodule Fibonacci do def fib(n) do fib(0, 1, [], n) end def fib(prev, curr, acc, n) do fib(curr, prev + curr, [curr | acc], n - 1) end end

Итак, строка 6 'fib(prev, curr, acc, n)' берет значения из строки 3 'fib(0, 1, [], 5)' и вводит эти значения в строку 7 'fib(curr, prev + curr, [curr | acc], n - 1)", которое станет "fib(1, 1+1, [ 1,[1]], 5-1)". Это когда рекурсия начинается, когда я вызываю функцию в теле той же функции, что означает, что она вызывает ту же функцию с новыми значениями и продолжает добавлять последовательность Фибоначчи к "acc". вот что происходит в строке 7
fib(1, 1+1, [ 1,[1] ], 5-1) → fib(1, 2, [ 1,[1] ], 4)
fib(2, 1+2, [ 2,[1,1] ], 4-1) → fib(2, 3, [ 2,[1,1] ], 3)
fib(3, 2+3, [ 3,[2,1,1] ], 3-1) → fib(3, 5, [ 3,[2,1,1] ], 2)
fib(5, 3+5, [ 5,[3,2,1,1] ], 2-1) -> fib(5, 8, [ 3,[2,1,1] ], 1)
fib(8, 5+8, [ 8,[5,3,2,1,1] ], 1-1) → fib(8, 13, [ 5,[3,2,1,1] ], 0)
Теперь значение "n" стало равным нулю, и мне нужно написать случай/функцию, что происходит, когда "n = 0", что, очевидно, возвращает последовательность в "acc", которая равна "[5,3,2,1,1] '
|› Возврат выхода из аккумулятора
строка 6 - это новая функция с 4 ариями, которая должна соответствовать шаблону с нашей предыдущей функцией, и она должна быть написана перед предыдущей функцией, чтобы компиляция вернула "acc", что "n = 0". я отключил первые два символа подчеркивания, так как они не требуются в этой функции.
defmodule Fibonacci do def fib(n) do fib(0, 1, [], n) end def fib(_prev, _curr, acc, 0) do acc end def fib(prev, curr, acc, n) do fib(curr, prev + curr, [curr | acc], n - 1) end end

Когда вы компилируете код, он возвращает следующее.

Как вы заметили, здесь отсутствует ноль, а также возвращаются значения в обратном порядке. ну это легко исправить.
|› перечисление
defmodule Fibonacci do def fib(n) do fib(0, 1, [], n) end def fib(_prev, _curr, acc, 0) do acc |> Enum.reverse() end def fib(prev, curr, acc, n) do fib(curr, prev + curr, [curr | acc], n - 1) end end

Добавьте ‘|› Enum.reverse()’ в строку 7 после ‘acc’, это меняет порядок списка в ‘acc’ и возвращает список, как показано ниже.

|› Изменение входных значений
Теперь для нуля я ввожу "[0]" в "acc" вместо пустого списка "[]", и это вернет 6 значений вместо 5 в последовательности, поэтому я также вычитаю "1" из "n".
defmodule Fibonacci do def fib(n) do fib(0, 1, [0], n - 1) end def fib(_prev, _curr, acc, 0) do acc |> Enum.reverse() end def fib(prev, curr, acc, n) do fib(curr, prev + curr, [curr | acc], n - 1) end end

После изменения строки 3, ниже возврат.

|› Отказоустойчивый
Я пошел немного дальше, чтобы защитить код от попадания в цикл, если пользователь вводит ноль, используя "если еще".
defmodule Fibonacci do
def fib(n) do
if n > 0 do
fib(0, 1, [0], n - 1)
else
"Please enter a value greater than zero"
end
end
def fib(_prev, _curr, acc, 0) do
acc |> Enum.reverse()
end
def fib(prev, curr, acc, n) do
fib(curr, prev + curr, [curr | acc], n - 1)
end
end

Возвращает
