> c("spawn/spawn-basic.ex")
[SpawnBasic]
> SpawnBasic.greet
Hello
:ok
> spawn(SpawnBasic, :greet, [])
Hello
#PID<0.108.0>
Kernel.spawn/3 指定したコードを実行するプロセスを生成する PID(プロセス識別子)を返す プロセスがいつ実行されるかはわからない
プロセス間でのメッセージの送信
Kernel.send/2 指定したプロセスにメッセージを送る アトムとタプルを送ることが多い
receive メッセージを待つ case文のようにメッセージのボディに応じて(パターンマッチ)で処理を振り分けられる
> c "spawn/spawn1.ex"
[Spawn1]
> pid = spawn(Spawn1, :greet, [])
#PID<0.107.0>
> send pid, {self, "World!"}
{#PID<0.100.0>, "World!"}
> receive do
> {:ok, message} ->
> IO.puts message
> end
Hello, World!
:ok
Kernel.self/0 自分自身のPIDを返す
複数のメッセージの処理
> c "spawn/spawn2.ex"
[Spawn2]
> pid = spawn(Spawn2, :greet, [])
#PID<0.107.0>
> send pid, {self, "World!"}
{#PID<0.100.0>, "World!"}
> receive do
> {:ok, message} ->
> IO.puts message
> end
Hello, World!
:ok
> send pid, {self, "Kermit!"}
{#PID<0.100.0>, "Kermit!"}
> receive do
> {:ok, message} ->
> IO.puts message
> end
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
(v)ersion (k)ill (D)b-tables (d)istribution
Spawn2.greet/1 は一度receiveを処理するとプロセスが終了する => 2度目のメッセージは処理されない
after タイムアウトまでの時間(ミリ秒)とタイムアウト時に行う処理を指定する
after 500 -> IO.puts "Timeout!"
> c "spawn/spawn3.ex"
[Spawn3]
> pid = spawn(Spawn3, :greet, [])
#PID<0.107.0>
> send pid, {self, "World!"}
{#PID<0.100.0>, "World!"}
> receive do
> {:ok, message} ->
> IO.puts message
> end
Hello, World!
:ok
> send pid, {self, "Kermit!"}
{#PID<0.100.0>, "Kermit!"}
> receive do
> {:ok, message} ->
> IO.puts message
> after 500 ->
> IO.puts "The greeter has gone away"
> end
The greeter has gone away
:ok
複数回処理する場合は、再帰を使う 最後に自分自身を呼び出す
> c "spawn/spawn4.ex"
Hello, World!
Hello, World!
[Spawn4]
再帰、ループ、スタック Elixirは、末尾再帰の場合、最適化されるので、スタックが積み上がってメモリ不足になることはない
最後の処理が再帰になっていないと、末尾再帰にはならない
末尾再帰でない例: 再帰呼び出し後、nをかけている
def factorial(0), do: 1
def factorial(n), do: n * factorial(n-1)
末尾再帰の例: アキュームレーターを追加する
defmodule TailRecursive do
def factorial(n), do: _fact(n, 1)
defp _fact(0, acc), do: acc
defp _fact(n, acc), do: _fact(n - 1, acc * n)
end
> c "spawn/fact_tr.ex"
[TailRecursive]
> TailRecursive.factorial(5)
120
> TailRecursive.factorial(1)
1
> TailRecursive.factorial(0)
1