Programming Elixir

Just trying out Elixir (http://elixir-lang.org/) using above book and screencast, as part of my concurrency series.

It’s functional programming language. I had been avoiding the purely functional languages after I studied Lisp at school, and only relationship with them was copy-pasting emacs lisp.

However, Elixir seems reasonably well structured for beginners with the essence of Ruby, while keeping the power of underlying Erlang VM. The official documents are still limited, but the book “Programming Elixir” provides a good guidance for understanding the interesting paradigm of this language.

Then the “Meet Elixir” screencast presented by José Valim describes good insights of background philosophy of Elixir, which is pretty much interesting and quite different from the standard object-oriented ones. The contents are relatively presented fast, so maybe it’s good to start from the book.

The power of Elixir would come out on the concurrency part – featured by Erlang VM. The following example (it’s from the book, though slightly modified) spawns 10000 processes, and each process counts up one. It just takes sub-second, interesting.

$ elixir chain.exs
time = 122ms, msg = Result is 10000

chain.exs

defmodule Chain do
@moduledoc """
Spawns Erlangs's lightweight processes for counting up numbers.
"""
# When receiving a number from the previous process, 'receive' block is executed with number 'n'.
# Then, propagate the 'n + 1' to the next process.
def counter(next_pid) do
receive do
n -> next_pid <- n + 1
end
end
# Creates 'n' number of processes to count upto 'n'
def create_processes(n) do
# loop 'n' times to spawn processes, then returns the process id of last one, which comprises
# of 'n' process chain starting from 'self' process.
last = Enum.reduce 1..n, self,
fn(_, send_to) -> spawn(Chain, :counter, [send_to]) end
# send the initial number 0 to the last process.
last <- 0
# wait for the 'n' length propagation to complete back to 'self'
receive do
final_answer when is_integer(final_answer) ->
"Result is #{inspect(final_answer)}"
end
end
# Execute the process creation with the timer count.
def run(n) do
{time, msg} = :timer.tc(Chain, :create_processes, [n])
IO.puts "time = #{div(time, 1000)} milliseconds, msg = #{msg}"
end
end
# spawning 10000 processes which each counts up one.
Chain.run(10000)