Yuri Leikind / @less_software
For our goal to write Hello World in BEAM in 20 minutes we're giving up on Erlang the language :-)
And we'll use Elixir, a BEAM language with modern syntax.
I want your brains cycles to be spent on the semantics of BEAM, and not on unfamiliar Erlang syntax.
Elixir is not Coffescript for Erlang!
It has some some really cool stuff of its own.
But here we're not looking at it.
We are only using features which are mapped to its Erlang equivalents.
So yes...
We are using Elixir as if it were Coffescript for Erlang...
Please don't tell anyone!
Because it isn't! :)
Idea © Dave Thomas
pid = spawn(fn() -> :ok end)
IO.inspect Process.alive?(pid)
IO.inspect Process.alive?(pid)
true
false
pid = spawn fn() ->
receive do
message -> IO.puts "received message: \"#{message}\""
end
end
IO.inspect Process.alive?(pid)
pid <- "Cheer up, beautiful people"
pid <- "this is where you get to make it right" # won't be received
:timer.sleep 100
IO.inspect Process.alive?(pid)
true
received message: "Cheer up, beautiful people"
false
defmodule Processes do
def loop do
receive do
message -> IO.puts "received message: \"#{message}\""
end
loop
end
def run do
pid = spawn Processes, :loop, []
pid <- "Cheer up, beautiful people"
pid <- "this is where you get to make it right"
end
end
Processes.run
received message: "Cheer up, beautiful people"
received message: "this is where you get to make it right"
defmodule Processes do
def loop do
receive do
{reply_to, message} ->
reply_to <- String.reverse(message)
end
loop
end
def run do
pid = spawn Processes, :loop, []
pid <- {self(), "Cheer up, beautiful people"}
pid <- {self(), "this is where you get to make it right"}
receive do
response -> IO.inspect(response)
end
receive do
response -> IO.inspect(response)
end
end
end
Processes.run
"elpoep lufituaeb ,pu reehC"
"thgir ti ekam ot teg uoy erehw si siht"
defmodule Processes do
def loop do
receive do
{reply_to, :reverse, message} ->
reply_to <- String.reverse(message)
{reply_to, :upcase, message} ->
reply_to <- String.upcase(message)
{reply_to, _, _message} ->
reply_to <- "What?"
end
loop
end
def run do
pid = spawn Processes, :loop, []
pid <- {self(), :upcase, "Cheer up, beautiful people"}
pid <- {self(), :reverse, "this is where you get to make it right"}
pid <- {self(), :say, "Say my name"}
receive do
response -> IO.inspect(response)
end
receive do
response -> IO.inspect(response)
end
receive do
response -> IO.inspect(response)
end
end
end
Processes.run
"CHEER UP, BEAUTIFUL PEOPLE"
"thgir ti ekam ot teg uoy erehw si siht"
"What?"
defmodule Processes do
def loop do
receive do
{reply_to, :reverse, message} ->
reply_to <- String.reverse(message)
loop
{reply_to, :upcase, message} ->
reply_to <- String.upcase(message)
loop
{reply_to, _, _message} ->
reply_to <- "What?"
loop
:shutdown ->
IO.puts "shutting down..."
:ok
end
end
def run do
pid = spawn Processes, :loop, []
pid <- {self(), :upcase, "Cheer up, beautiful people"}
receive do
response -> IO.inspect(response)
end
pid <- :shutdown
:timer.sleep 100
IO.inspect Process.alive?(pid)
end
end
Processes.run
"CHEER UP, BEAUTIFUL PEOPLE"
shutting down...
false
defmodule MyOwn do
def map([], _) do
[]
end
def map([head|tail], function) do
[function.(head) | map(tail, function)]
end
end
IO.inspect MyOwn.map([1,2,3,4], fn(e) -> e * e end)
[1, 4, 9, 16]
defmodule TheHelloWordOfErlang do
def process_one_element_and_send_return(function, element, pid) do
pid <- {self(), function.(element)}
end
def concurrent_map(list, function) do
parent_process_pid = self()
pids = Enum.map(
list,
fn(element) ->
spawn(TheHelloWordOfErlang, :process_one_element_and_send_return, [function, element, parent_process_pid])
end
)
Enum.map(
pids,
fn(pid)->
receive do
{^pid, result} -> result
end
end
)
end
end
func = fn(e)-> e * e end
IO.inspect TheHelloWordOfErlang.concurrent_map([1,2,3,4,5], func)
TheHelloWordOfErlang.concurrent_map(1..10_000, func)
defmodule TheHelloWordOfErlang do
def concurrent_map(list, function) do
parent_process_pid = self()
pids = Enum.map(
list,
fn(element) ->
spawn(
fn ->
parent_process_pid <- {self(), function.(element)}
end
)
end
)
Enum.map(
pids,
fn(pid)->
receive do
{^pid, result} -> result
end
end
)
end
end
func = fn(e)-> e * e end
IO.inspect TheHelloWordOfErlang.concurrent_map([1,2,3,4,5], func)
TheHelloWordOfErlang.concurrent_map(1..10_000, func)
[1, 4, 9, 16, 25]
defmodule TheHelloWordOfErlang do
def concurrent_map(list, function) do
parent_process_pid = self()
pids = Enum.map(
list,
fn(element) ->
spawn(
fn ->
parent_process_pid <- {self(), function.(element)}
end
)
end
)
Enum.map(
pids,
fn(pid)->
receive do
{^pid, result} -> result
end
end
)
end
end
func = fn(e)-> e * e end
IO.inspect TheHelloWordOfErlang.concurrent_map([1,2,3,4,5], func)
TheHelloWordOfErlang.concurrent_map(1..10_000, func)
[1, 4, 9, 16, 25]
defmodule TheHelloWordOfErlang do
def concurrent_map list, function do
parent_process_pid = self
list |>
Enum.map(&(
spawn fn -> parent_process_pid <- {self(), function.(&1)} end
)) |>
Enum.map &(receive do: ({^&1, result} -> result))
end
end
func = fn(e)-> e * e end
IO.inspect TheHelloWordOfErlang.concurrent_map([1,2,3,4,5], func)
TheHelloWordOfErlang.concurrent_map(1..10_000, func)
[1, 4, 9, 16, 25]