scalable and maintainable applications. Elixir leverages the Erlang VM, known for running low-latency, distributed and fault-tolerant systems, while also being successfully used in web development and the embedded software domain. — http://www.elixir-lang.org
parallel and the primitives provided by most languages are quite low level • Runs on top of the Erlang runtime, famous for amazing uptimes and fault tolerance • Powerful macro system for creating DSLs and reducing boilerplate • OTP library and architecture makes it easier to create fault tolerant systems
sockets to web servers and frameworks) • Writing reliable, distributed, and highly available software • MMO backends (not frontends!) • Using all the cores • (AKA Things Erlang Is Good For)
leiningen • Like Make/Rake it can compile and runs tests • Like Bundler it allows dependencies to be specified • Like Rails or Bundler it can generate new project skeletons • Full integration with Erlang, Rebar, and hex.pm
Integer do def blank?(_), do: false end # Just empty list is blank defimpl Blank, for: List do def blank?([]), do: true def blank?(_), do: false end #... 1 Sorry, the syntax highlighter doesn't know about protocols yet
[], name: __MODULE__ end def init(_) do GenServer.cast __MODULE__, :stream { :ok, nil } end def handle_cast(:stream, state) do spawn_link fn -> RedirectCounter.Twitter.links |> Enum.each(&RedirectCounter.CounterSupervisor.process/1) end { :noreply, state } end end
[], name: __MODULE__ end def log(redirect_count) do GenServer.cast __MODULE__, { :redirect_count, redirect_count } end def get do GenServer.call __MODULE__, :get end def init(_) do { :ok, %{} } end def handle_cast({:redirect_count, redirect_count}, state) do state = Map.update(state, redirect_count, 1, fn(n) -> n + 1 end) { :noreply, state } end def handle_call(:get, _from, state) do { :reply, state, state } end end
redirect_count}, state) do state = Map.update(state, redirect_count, 1, fn(n) -> n + 1 end) { :noreply, state } end def handle_call(:get, _from, state) do { :reply, state, state } end
end def init(_) do children = [ worker(RedirectCounter.Count, []), worker(RedirectCounter.ConsoleOutput, []), supervisor(RedirectCounter.CounterSupervisor, []), worker(RedirectCounter.TwitterLinkStream, []) ] supervise(children, strategy: :one_for_one) end end
[], name: __MODULE__ end def process(url) do {:ok, pid} = Supervisor.start_child(__MODULE__, [url]) GenServer.cast(pid, :count) end def init(_) do children = [ worker(RedirectCounter.URLRedirectCounter, [], restart: :temporary, shutdown: :brutal_kill) ] supervise(children, strategy: :simple_one_for_one) end end
end def init(url) do { :ok, url } end def handle_cast(:count, url) do redirect_count = RedirectCounter.URL.count_redirects(url) RedirectCounter.Count.log(redirect_count) { :stop, :normal, url } end end
operation which is dangerous and might crash, you "outsource" that computation to another process, a dumb slave worker. If he crashes and is killed, nothing really bad has happened - since the kernel keeps going. — Jesper Louis Anderson
do GenServer.start_link __MODULE__, [], name: __MODULE__ end def log(redirect_count) do GenServer.cast __MODULE__, { :redirect_count, redirect_count } end def get do GenServer.call __MODULE__, :get end def init(_) do { :ok, %{} } end def handle_cast({:redirect_count, redirect_count}, state) do state = Map.update(state, redirect_count, 1, fn(n) -> n + 1 end) { :noreply, state } end def handle_call(:get, _from, state) do { :reply, state, state } end end
-> %{} end, name: __MODULE__) end def log(redirect_count) do Agent.update(__MODULE__, &Map.update(&1, redirect_count, 1, fn(n) -> n + 1 end)) end def get do Agent.get(__MODULE__, fn(map) -> map end) end end
def start_link do Supervisor.start_link(__MODULE__, []) end def init(_) do children = [ worker(RedirectCounter.Count, []), worker(RedirectCounter.ConsoleOutput, []), supervisor(RedirectCounter.CounterSupervisor, []), worker(RedirectCounter.TwitterLinkStream, []) ] supervise(children, strategy: :one_for_one) end end
def start_link do Supervisor.start_link(__MODULE__, []) end def init(_) do children = [ worker(RedirectCounter.Count, []), worker(RedirectCounter.ConsoleOutput, []), supervisor(Task.Supervisor, [[name: :counter_supervisor]]), worker(Task, [RedirectCounter.Twitter, :process, [&RedirectCounter.URL.process/1]]) ] supervise(children, strategy: :one_for_one) end end
(in Erlang terminology) • Upgrades and hot code reloading • Debugging, monitoring, and logging • The other parts of OTP (ssh, asn.1, ...) • ets / mnesia (built in "NoSQL" databases)