Files
elixir-koans/lib/koans/15_processes.ex
Ahmed Ismail edf50fdf80 Add credo to the project and:
- 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
2023-11-10 00:57:21 +05:00

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