patternMinor
Tail Recursion for Sum - Elixir
Viewed 0 times
recursionelixirtailforsum
Problem
I'm new to both Elixir and tail recursion.
Is the above an optimal way to calculate the sum up to x?
defmodule MyInteger do
defp sum_upto(x, accumulator) when accumulator 1 do
sum_upto(x, accumulator-1) + accumulator
end
def sum_upto(x) when x <= 1 do
x
end
def sum_upto(x) do
sum_upto(x, x-1) + x
end
endIs the above an optimal way to calculate the sum up to x?
Solution
Overview
I see that there are some good comments and I thought I'd just explain in a full answer block -- I'm not on here too often so I apologize for the tardiness of the response. Bear with me as I first show you what I might really do then demonstrate the answer to your tail recursive question using the same terms with which you posed your question.
What I Would Do
First, I think you are asking how to add up the numbers 1,2,3,...,x.
I would actually use the Enum.reduce function:
or using Elixir capture syntax which is more concise and obtuse:
The Main Question
Now to the crux of your actual question, how would I do this without using Enum and using tail recursion. First note that the last entry in the function call will be the function itself. There must be no other add, sub, multiply, -- operation of any kind before or after the function call. You can change the parameters but don't do anything outside call itself.
Here is a simple tail recursive routine that adds numbers up:
I wrote this counting down to make it like your example. When you first call MyInteger.sum_to_x(20, 0) the second form of the sum_to_x function is used. We pass 0 as the initial value of the accumulator. The last line in that function calls itself and nothing else (tail recursive). That is when the function finally "returns" there are no other ops to do. This function will call itself counting x down until x is zero. When is is zero, we match the first form of the function since we have a "0" in the first parameter. This form just returns the accumulated result --
uDude
I see that there are some good comments and I thought I'd just explain in a full answer block -- I'm not on here too often so I apologize for the tardiness of the response. Bear with me as I first show you what I might really do then demonstrate the answer to your tail recursive question using the same terms with which you posed your question.
What I Would Do
First, I think you are asking how to add up the numbers 1,2,3,...,x.
I would actually use the Enum.reduce function:
1..20 |> Enum.reduce(0, fn(x,acc) -> acc + x end)or using Elixir capture syntax which is more concise and obtuse:
1..20 |> Enum.reduce(0, &(&1 + &2))The Main Question
Now to the crux of your actual question, how would I do this without using Enum and using tail recursion. First note that the last entry in the function call will be the function itself. There must be no other add, sub, multiply, -- operation of any kind before or after the function call. You can change the parameters but don't do anything outside call itself.
Here is a simple tail recursive routine that adds numbers up:
defmodule MyInteger do
def sum_to_x(0, acc) do
acc
end
# initial function call
def sum_to_x(x, acc) do
sum_to_x(x - 1, acc + x)
end
end
IO.puts MyInteger.sum_to_x(20, 0)I wrote this counting down to make it like your example. When you first call MyInteger.sum_to_x(20, 0) the second form of the sum_to_x function is used. We pass 0 as the initial value of the accumulator. The last line in that function calls itself and nothing else (tail recursive). That is when the function finally "returns" there are no other ops to do. This function will call itself counting x down until x is zero. When is is zero, we match the first form of the function since we have a "0" in the first parameter. This form just returns the accumulated result --
uDude
Code Snippets
1..20 |> Enum.reduce(0, fn(x,acc) -> acc + x end)1..20 |> Enum.reduce(0, &(&1 + &2))defmodule MyInteger do
def sum_to_x(0, acc) do
acc
end
# initial function call
def sum_to_x(x, acc) do
sum_to_x(x - 1, acc + x)
end
end
IO.puts MyInteger.sum_to_x(20, 0)Context
StackExchange Code Review Q#121307, answer score: 3
Revisions (0)
No revisions yet.