I want to make a program to prints number from 1 to N starting in 1 without an accumulator.
defmodule Recursion do
def print_multiple_times(n) when n <= 1 do
IO.puts n
end
def print_multiple_times( n) do
IO.puts n
print_multiple_times( n - 1)
end
end
I want to do something like this, but instead of going from n to 1 (n - 1) going from 1 to n, but without an accumulator I can’t find any solution.
defmodule Recursion do
def print_multiple_times(n) when n >= 10 do
IO.puts n
end
def print_multiple_times( n) do
IO.puts n
print_multiple_times( n + 1)
end
end
but in this case, You set n as starting point. You could pass m value as the end point.
This is not esoteric, but the only true way, as all the other versions actually create a list that we are not interested in. Since we are only interested in the side effects of printing, actually only Enum.each/2 or some stream that is piped into Stream.run/1 are valid answers.
Yes, perhaps “esoteric” was not my best choice of words. I get the feeling the original poster was trying various approaches out and there was no strict constraint. If there was a constraint to not create a list, then I apologize for my irrelevant post. At least I didn’t use an accumulator
Additional parameters are a legitimate technique for controlling recursion. With tail recursion (without side effects like IO.puts) one parameter is used to managing the data that is left on the call stack with body recursion.
defmodule Demo do
def multi(n),
do: multi(1, n, [])
defp multi(i, n, list) when i > n,
do: list
defp multi(i, n, rest) when i <= n,
do: multi(i + 1, n, [i | rest])
end
result = Demo.multi(10)
IO.puts("#{inspect(result, charlists: :as_lists)}")
r = :lists.reverse(result)
IO.puts("#{inspect(r, charlists: :as_lists)}")
I didn’t mean to scare you away, sorry if I did. I’m not sure if the original poster needed a list, but from the example code, the Enum.each/2 is closest.
I was driving towards the realization that the original code has in fact a hardcoded limit - as demonstrated by @kokolegorille.
So going the other way doesn’t actually need an additional parameter. It’s just that the original code left one out by hardcoding it.
defmodule Recursion do
def print_multiple_times(n, m) when n <= m do
IO.puts(n)
end
def print_multiple_times(n, m) do
IO.puts(n)
print_multiple_times(n - 1, m)
end
def print_multiple_times_r(n, m) when n >= m do
IO.puts(n)
end
def print_multiple_times_r(n, m) do
IO.puts(n)
print_multiple_times_r(n + 1, m)
end
def multi(n, m) when n >= m,
do: print_multiple_times(n, m)
def multi(n, m),
do: print_multiple_times_r(n, m)
end
Recursion.multi(10, 1)
Recursion.multi(1, 10)
Recursion.multi(10, 10)
Yeah, the Enum.each/2 was closest, but honestly, I like @kokolegorille 's example for comprehension most. As I learned from José’s Advent of Code videos, a for comprehension that is not assigned to a variable does not generate the intermediate list either.