3 ms·
Good stuff. I've started using Elixir and Phoenix in a new project (I wanted concurrency for making a lot of HTTP calls) and while functional programming does t
by firasd 10y ago
Good stuff. I've started using Elixir and Phoenix in a new project (I wanted concurrency for making a lot of HTTP calls) and while functional programming does take getting used to (you can not write something like a counter that increments itself in a loop) it's been relatively easy to pick up. Compared to learning Node.js, it's been a more relaxed and productive experience (although maybe I'm not making a fair comparison because I've implemented way more things in Node that I have yet to try in Elixir.)
- jdimov10 10y agoElixir counter in a loop: defmodule LoopCounter do def go, do: go(0) defp go(n) do IO.puts("n is #{n}") :timer.sleep(1000) go(n + 1) end end Or you can use processes and message passing to maintain state. More examples at: http://dantswain.herokuapp.com/blog/2015/01/06/storing-state-in-elixir-with-processes/ http://dantswain.herokuapp.com/blog/2015/01/06/storing-state...
- firasd 10y agoInteresting. I was trying to do something like: tasks = for i <- urls do Task.start(fn -> :timer.sleep(5000 * the_counter) # more stuff end) end So each task would run 5 seconds after the previous one, etc. I definitely need a deeper understanding of the whole environment and language though. Will check out the article.
- tomku 10y agoHere's a couple ways of doing that, packaged as a runnable .exs script that you can mess around with: https://gist.github.com/tomku/21eab22e98950f31a072a2ac63900b16 https://gist.github.com/tomku/21eab22e98950f31a072a2ac63900b... The key ingredient is Enum.with_index, which pairs your enumerable with the indices that you'd have in an iterative 'for' loop in another language. I've also changed from Task.start to Task.async so that I can collect the tasks and wait for them at the end of the script. Edit: The recursive approach jdimov10 explained is really useful too, you'll see that pattern of using a recursive function's arguments to hold state all over the functional programming world.
- firasd 10y agoThanks for the code sample! Will give it a try.
- unvs 10y agoNot exactly what you want, but I've found this snippet useful from time to time: for {item, counter} <- Enum.with_index([:a, :b, :c]) do IO.puts("#{counter} -> #{item}") end 0 -> a 1 -> b 2 -> c
- pdimitar 10y agoThat's actually a perfect example of looping over data structures. Thank you. (Yes, not what the parent poster asked but I still found it useful.)
- shadeless 10y agoOr if you like pipelines as much as I do, you can write it as: [:a, :b, :c] |> Enum.with_index |> Enum.each(fn({item, counter}) -> IO.puts("#{counter} -> #{item}") end)
- sanderjd 10y agoThis is interesting. I'm a huge fan of pipelines like that and I think they're unmatched for being able to compose operations well, but I prefer the non-pipelines version of what is basically just an imperative loop.
- innocentoldguy 10y agoIf all you want is a counter to loop through something a given number of times, you could do something like this: defmodule Counter do def loop(num) do Enum.each(0..num, fn (i) -> IO.puts(i) end) end end If you really want to write your own recursive function (Enum already does that for you, but it's always good to try different ways, so you can learn the language better), you could do something like this: defmodule Counter do def loop(num), do: _loop(0, num) defp _loop(idx, num) when idx == num, do: IO.puts idx defp _loop(idx, num) do IO.puts idx _loop(idx + 1, num) end end The thing that is nice about Elixir is that it does tail-optimization on its recursive functions, as long as the recursive call is the very last thing in the function. This means you won't have 10 copies of the _loop function in memory waiting to unwind.