Skip to content

Latest commit

 

History

History
151 lines (128 loc) · 2.89 KB

14.1.md

File metadata and controls

151 lines (128 loc) · 2.89 KB
> 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