(1998) • Originally used in Telephony Applications • Functional • Everything is a process • Processes send messages to other processes (or themselves) • Processes have a mailbox to receive messages • Fault tolerant • Immutable • Tail-optimized recursion • Pattern matching
“processes” and “threads” ◦ Processes are super light-weight ◦ Not implemented using underlying OS ◦ Processes get preempted by the VM scheduler so that resources aren’t hogged. • Has compilation step ◦ Can also generate a standalone binary • Garbage collection at the individual process level ◦ Doesn’t “Stop The World” • Has many tweaking switches, similar to the JVM • Attempts to keep all CPUs occupied
learn ◦ Turns people off to the language • Ruby has nice syntax • How about make Erlang look more like Ruby? ◦ Instead of having to learn functional concepts and a funky syntax, can focus on the former. • Invented by José Valim at Plataformatec • Can utilize existing Erlang code • Adds generalized macros, protocols
upon • Anytime a change is needed, new memory is allocated • Messages sent to other process are copied to that process’s heap • More deterministic • Easier to reason about ◦ E.g. don’t have to look at other methods to see how they might munge an instance variable
detect when processes crash and immediately spin them back up • A process crash doesn’t have to affect any other processes ◦ They can continue as if nothing happened • Lots of 9s in uptime stats are possible: 99.9999999%
• No more Thread declarations, Mutexes, Semaphores, Synchonizing ◦ Create lots of bugs ◦ Also bottlenecks ◦ Steep learning curve • Spin up a process • Give it a name • Give it an initial state • Let it go off and do its thing • Get the result, if need be • Memory is copied; everything is immutable • Will utilize all cores available to the VM
Need super high availability • Amazon ◦ SimpleDB, distributed database • Facebook ◦ Parts of their messaging platform • WhatsApp (recently bought by Facebook) • Basho ◦ Riak
prepending to the list • ++ operator for appending to the list ◦ Generally best to use cons and reverse list than ++ iex(1)> my_list = [1,2,3] [1, 2, 3] iex(2)> prepended_zero = [0 | my_list] [0, 1, 2, 3] iex(3)> appended_four = prepended_zero ++ [4] [0, 1, 2, 3, 4] iex(4)> Enum.reverse(appended_four) [4, 3, 2, 1, 0]
Like a named Map. defmodule Person do defstruct first: “”, last: “”, dob: “”, voted_for: “Mickey Mouse” def generate_person(first, last, dob, voted_for) do %Person{first: first, last: last, dob: dob, voted_for: voted_for} end end
Tuples • Dicts ◦ deprecated • Keywords ◦ list of tuples where the first element is an Atom, and the second is any value • Sets ◦ unique, similar to Ruby’s
assignment • It is a declaration that the left and right sides must be equal iex(1)> a = 1 1 iex(2)> a = 2 2 iex(3)> 2 = a 2 iex(4)> 3 = a ** (MatchError) no match of right hand side value: 2
Starts at the first one, and if no pattern match, continues to the next • When a function matches the arguments, that is the one executed • The example below is absurd, but attempts to demonstrate: def add(0, x), do: x def add(x, 0), do: x def add(x, y), do: x + y
Now we want to change behavior based on a characteristic defmodule PrintStuff do def greeting(x) when is_integer(x), do: IO.puts “Hi, number #{x}” def greeting(x) when is_binary, do: IO.puts “Hello, string #{x}” def greeting(_), do: “Hello, but I’m unsure of what you are” end
defmodule PrintStuff do def type(x) when is_integer(x) and rem(x, 2) == 0, do: "even" def type(x) when is_integer(x), do: "odd" def type(x), do: "unknown" end
previous result as the first argument to the next function • Ever find yourself doing this, in Ruby, for example? do_another_thing(do_something_else(do_something(x))) • How about this instead? x |> do_something |> do_something_else |> do_another_thing
things where we would use loops in Ruby • Tail recursion optimization (therefore, no stack memory problems) defmodule Count do def up_to(x), do: up_to(x, 0, []) |> Enum.reverse defp up_to(x, n, numbers) when n > x, do: numbers defp up_to(x, n, numbers), do: up_to(x, n + 1, [n | numbers]) end iex(1)> Count.up_to(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
be spawned • Can have messages sent to them with send • Can receive messages in return • receive is the only way to suspend a Process ◦ waits for a message ◦ A timeout can be specified, if desired • The core mechanism for maintaining state in Erlang and Elixir.