(where x is an integer >= 0)
Is there a one-liner for this?
I found that Enum.times was deprecated back in in 2012:
But it seems that ranges aren’t a proper replacement, since they don’t work for the case where x == 0.
(where x is an integer >= 0)
Is there a one-liner for this?
I found that Enum.times was deprecated back in in 2012:
But it seems that ranges aren’t a proper replacement, since they don’t work for the case where x == 0.
Ranges work fine with 0.
Enum.each(0..x, fn i -> do_something(i) end)
If you mean the specific case of 0..0
, it can be dealt with like this
Enum.each(0..x, fn
0 -> :nothing
_ -> do_something()
end)
Right, I was just wondering if there was something that more directly replaced Enum.times that I missed. Thanks!
iex(5)> for i <- 0..10, i > 0, do: IO.puts i
1
2
3
4
5
6
7
8
9
10
[:ok, :ok, :ok, :ok, :ok, :ok, :ok, :ok, :ok, :ok]
iex(6)> for i <- 0..0, i > 0, do: IO.puts i
[]
Yeah that’s more what I was looking for. Thanks!
Keep in mind that the intent of comprehensions is to work with Enumerables which Range happens to implement. Hence the “result” of the comprehension is a list of :ok
values; in this particular case the side-effect is the intended behaviour.
Now you can suppress the list of :ok
values by abusing the filter expression:
iex(1)> for x <- 0..10, (fn i -> if (i > 0), do: IO.puts i; false end).(x), do: :ok
1
2
3
4
5
6
7
8
9
10
[]
But that’s really going from bad to worse.
There is nothing stopping you from creating your own “one-liner”:
iex(2)> do_it = fn (low,high,f) ->
...(2)> aux = fn
...(2)> c,i when i <= high ->
...(2)> f.(i)
...(2)> c.(c, i+1)
...(2)> _,_ ->
...(2)> :ok
...(2)> end
...(2)> aux.(aux,low)
...(2)> end
#Function<18.99386804/3 in :erl_eval.expr/5>
iex(3)> do_it.(0,10,&IO.puts/1)
0
1
2
3
4
5
6
7
8
9
10
:ok
iex(4)>
Otherwise I’d just stick with Enum.each/2
.
It appeared that Range type in Elixir has step
:
iex(1)> Map.from_struct(1..0)
%{first: 1, last: 0, step: -1}
So it’s possible to overcome the “do nothing” problem via this range creation syntax:
for _ <- 1..n//1, do: something()
This loop will call something() n
times, and will NOT call it at all when n == 0
See Range — Elixir v1.13.4 for more examples
Stream.repeatedly(...) |> Enum.take(n)
Or Stream.iterate
if you really just want increments.