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

Прошел месяц с тех пор, как я начал изучать программирование на Эликсире, сегодня мне удалось написать код для получения последовательности Фибоначчи самостоятельно, без обращения к какой-либо документации или помощи моего учителя.
И это заняло всего 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

Возвращает
