Do something x number of times

(where x is an integer >= 0)

Is there a one-liner for this?

I found that Enum.times was deprecated back in in 2012:
https://github.com/elixir-lang/elixir/issues/619

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)
2 Likes

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)
2 Likes

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 
[]
6 Likes

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.