
- Run mix credo --all to identify possible code optimizations - Resolve most of the errors generated by credo such as: - Numbers larger than 9999 should be written with underscores: 58_127 - Modules should have a @moduledoc tag - Comparison will always return true
194 lines
4.0 KiB
Elixir
194 lines
4.0 KiB
Elixir
defmodule Processes do
|
|
@moduledoc false
|
|
use Koans
|
|
|
|
@intro "Processes"
|
|
|
|
koan "You are a process" do
|
|
assert Process.alive?(self()) == ___
|
|
end
|
|
|
|
koan "You can ask a process to introduce itself" do
|
|
information = Process.info(self())
|
|
|
|
assert information[:status] == ___
|
|
end
|
|
|
|
koan "Processes are referenced by their process ID (pid)" do
|
|
assert is_pid(self()) == ___
|
|
end
|
|
|
|
koan "New processes are spawned functions" do
|
|
value =
|
|
spawn(fn ->
|
|
receive do
|
|
end
|
|
end)
|
|
|
|
assert is_pid(value) == ___
|
|
end
|
|
|
|
koan "Processes die when their function exits" do
|
|
fast_process = spawn(fn -> :timer.sleep(10) end)
|
|
slow_process = spawn(fn -> :timer.sleep(1000) end)
|
|
|
|
# All spawned functions are executed concurrently with the current process.
|
|
# You check back on slow_process and fast_process 50ms later. Let's
|
|
# see if they are still alive!
|
|
:timer.sleep(50)
|
|
|
|
assert Process.alive?(fast_process) == ___
|
|
assert Process.alive?(slow_process) == ___
|
|
end
|
|
|
|
koan "Processes can send and receive messages" do
|
|
send(self(), "hola!")
|
|
|
|
receive do
|
|
msg -> assert msg == ___
|
|
end
|
|
end
|
|
|
|
koan "A process will wait forever for a message" do
|
|
wait_forever = fn ->
|
|
receive do
|
|
end
|
|
end
|
|
|
|
pid = spawn(wait_forever)
|
|
|
|
assert Process.alive?(pid) == ___
|
|
end
|
|
|
|
koan "Received messages are queued, first in first out" do
|
|
send(self(), "hola!")
|
|
send(self(), "como se llama?")
|
|
|
|
first_message =
|
|
receive do
|
|
message -> message
|
|
end
|
|
|
|
second_message =
|
|
receive do
|
|
message -> message
|
|
end
|
|
|
|
assert first_message == ___
|
|
assert second_message == ___
|
|
end
|
|
|
|
koan "A common pattern is to include the sender in the message, so that it can reply" do
|
|
greeter = fn ->
|
|
receive do
|
|
{:hello, sender} -> send(sender, :how_are_you?)
|
|
end
|
|
end
|
|
|
|
pid = spawn(greeter)
|
|
|
|
send(pid, {:hello, self()})
|
|
|
|
# ms
|
|
timeout = 100
|
|
|
|
failure_message =
|
|
"Sorry, I didn't get the right message. Look at the message that is sent back very closely, and try again"
|
|
|
|
assert_receive ___, timeout, failure_message
|
|
end
|
|
|
|
def yelling_echo_loop do
|
|
receive do
|
|
{caller, value} ->
|
|
send(caller, String.upcase(value))
|
|
yelling_echo_loop()
|
|
end
|
|
end
|
|
|
|
koan "Use tail recursion to receive multiple messages" do
|
|
pid = spawn_link(&yelling_echo_loop/0)
|
|
|
|
send(pid, {self(), "o"})
|
|
assert_receive ___
|
|
|
|
send(pid, {self(), "hai"})
|
|
assert_receive ___
|
|
end
|
|
|
|
def state(value) do
|
|
receive do
|
|
{caller, :get} ->
|
|
send(caller, value)
|
|
state(value)
|
|
|
|
{caller, :set, new_value} ->
|
|
state(new_value)
|
|
end
|
|
end
|
|
|
|
koan "Processes can be used to hold state" do
|
|
initial_state = "foo"
|
|
|
|
pid =
|
|
spawn(fn ->
|
|
state(initial_state)
|
|
end)
|
|
|
|
send(pid, {self(), :get})
|
|
assert_receive ___
|
|
|
|
send(pid, {self(), :set, "bar"})
|
|
send(pid, {self(), :get})
|
|
assert_receive ___
|
|
end
|
|
|
|
koan "Waiting for a message can get boring" do
|
|
parent = self()
|
|
|
|
spawn(fn ->
|
|
receive do
|
|
after
|
|
5 -> send(parent, {:waited_too_long, "I am impatient"})
|
|
end
|
|
end)
|
|
|
|
assert_receive ___
|
|
end
|
|
|
|
koan "Trapping will allow you to react to someone terminating the process" do
|
|
parent = self()
|
|
|
|
pid =
|
|
spawn(fn ->
|
|
Process.flag(:trap_exit, true)
|
|
send(parent, :ready)
|
|
|
|
receive do
|
|
{:EXIT, _pid, reason} -> send(parent, {:exited, reason})
|
|
end
|
|
end)
|
|
|
|
receive do
|
|
:ready -> true
|
|
end
|
|
|
|
Process.exit(pid, :random_reason)
|
|
|
|
assert_receive ___
|
|
end
|
|
|
|
koan "Parent processes can trap exits for children they are linked to" do
|
|
Process.flag(:trap_exit, true)
|
|
spawn_link(fn -> Process.exit(self(), :normal) end)
|
|
|
|
assert_receive {:EXIT, _pid, ___}
|
|
end
|
|
|
|
koan "If you monitor your children, you'll be automatically informed of their departure" do
|
|
spawn_monitor(fn -> Process.exit(self(), :normal) end)
|
|
|
|
assert_receive {:DOWN, _ref, :process, _pid, ___}
|
|
end
|
|
end
|