4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Elixirの対話モードでプロセスの動作を確認してみた

Posted at

概要

Elixirの対話モードでプロセスの動作を確認してみました。以下のページを参考にしました。

対話モードで実行

以下のコマンドを実行しました。

$ iex
Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> spawn fn -> 1 + 2 end
#PID<0.108.0>
iex(2)> pid = self()
#PID<0.106.0>
iex(3)> Process.alive?(pid)
true
iex(4)> defmodule Example do
...(4)> def add(a, b) do
...(4)> IO.puts(a + b)
...(4)> end
...(4)> end
{:module, Example,
 <<70, 79, 82, 49, 0, 0, 5, 20, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 154,
   0, 0, 0, 17, 14, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 109, 112, 108,
   101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:add, 2}}
iex(5)> spawn(Example, :add, [2, 3])
5
#PID<0.120.0>
iex(6)> send self(), {:hello, "world"}
{:hello, "world"}
iex(7)> receive do
...(7)> {:hello, msg} -> msg
...(7)> {:world, msg} -> "won't match"
...(7)> end
warning: variable "msg" is unused (if the variable is not meant to be used, prefix it with an underscore)
  iex:9

"world"
iex(8)> receive do
...(8)> {:hello, msg}  -> msg
...(8)> after
...(8)> 1_000 -> "nothing after 1s"
...(8)> end
"nothing after 1s"
iex(9)> parent = self()
#PID<0.106.0>
iex(10)> spawn fn -> send(parent, {:hello, self()}) end
#PID<0.133.0>
iex(11)> receive do
...(11)> {:hello, pid} -> "Got hello from #{inspect pid}"
...(11)> end
"Got hello from #PID<0.133.0>"
iex(12)> send self(), :hello
:hello
iex(13)> send self(), :world
:world
iex(14)> flush()
:hello
:world
:ok
iex(15)> flush()
:ok
iex(16)> defmodule Example do
...(16)> def listen do
...(16)> receive do
...(16)> {:hello, msg} -> IO.puts(msg)
...(16)> end
...(16)> end
...(16)> end
warning: redefining module Example (current version defined in memory)
  iex:16

{:module, Example,
 <<70, 79, 82, 49, 0, 0, 5, 52, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 161,
   0, 0, 0, 17, 14, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 109, 112, 108,
   101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:listen, 0}}
iex(17)> pid = spawn(Example, :listen, [])
#PID<0.152.0>
iex(18)> send pid, {:hello, "world"}
world
{:hello, "world"}
iex(19)> send pid, {:hello, "tokyo"}
{:hello, "tokyo"}
iex(20)> defmodule Example do
...(20)> def listen do
...(20)> receive do
...(20)> {:hello, msg} -> IO.puts(msg)
...(20)> end
...(20)> listen
...(20)> end
...(20)> end
warning: redefining module Example (current version defined in memory)
  iex:20

warning: variable "listen" does not exist and is being expanded to "listen()", please use parentheses to remove the ambiguity or change the variable name
  iex:25: Example.listen/0

{:module, Example,
 <<70, 79, 82, 49, 0, 0, 5, 76, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 161,
   0, 0, 0, 17, 14, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 109, 112, 108,
   101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:listen, 0}}
iex(21)> send pid, {:hello, "world"}
{:hello, "world"}
iex(22)> send pid, {:hello, "tokyo"}
{:hello, "tokyo"}
iex(23)> spawn fn -> raise "oops" end
#PID<0.169.0>
iex(24)> 
13:50:42.004 [error] Process #PID<0.169.0> raised an exception
** (RuntimeError) oops
    (stdlib 3.17) erl_eval.erl:683: :erl_eval.do_apply/6
 
nil
iex(25)> self()
#PID<0.106.0>
iex(26)> spawn_link fn -> raise "oops" end
** (EXIT from #PID<0.106.0>) shell process exited with reason: an exception was raised:
    ** (RuntimeError) oops
        (stdlib 3.17) erl_eval.erl:683: :erl_eval.do_apply/6

Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)

13:51:26.473 [error] Process #PID<0.173.0> raised an exception
** (RuntimeError) oops
    (stdlib 3.17) erl_eval.erl:683: :erl_eval.do_apply/6
iex(1)> defmodule Example do
...(1)> def explode, do: exit(:boom)
...(1)> end
warning: redefining module Example (current version defined in memory)
  iex:1

{:module, Example,
 <<70, 79, 82, 49, 0, 0, 4, 208, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 151,
   0, 0, 0, 16, 14, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 109, 112, 108,
   101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:explode, 0}}
iex(2)> spawn(Example, :explode, [])
#PID<0.182.0>
iex(3)> spawn_link(Example, :explode, [])
** (EXIT from #PID<0.174.0>) shell process exited with reason: :boom

Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> defmodule Example do
...(1)> def explode, do: exit(:boom)
...(1)> def run do
...(1)> Process.flag(:trap_exit, true)
...(1)> spawn_link(Example, :explode, [])
...(1)> receive do
...(1)> {:EXIT, from_pid, reason} -> IO.puts("Exit reason: #{reason}")
...(1)> end
...(1)> end
...(1)> end
warning: redefining module Example (current version defined in memory)
  iex:1

warning: variable "from_pid" is unused (if the variable is not meant to be used, prefix it with an underscore)
  iex:7: Example.run/0

{:module, Example,
 <<70, 79, 82, 49, 0, 0, 7, 152, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 1, 2, 0,
   0, 0, 28, 14, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 109, 112, 108,
   101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:run, 0}}
iex(2)> Example.run
Exit reason: boom
:ok
iex(3)> defmodule Example do
...(3)> def explode, do: exit(:boom)
...(3)> def run do
...(3)> {_pid, _ref} = spawn_monitor(Example, :explode, [])
...(3)> receive do
...(3)> {:DOWN, _ref, :process, _from_pid, reason} -> IO.puts("Exit reason: #{reason}")
...(3)> end
...(3)> end
...(3)> end
warning: redefining module Example (current version defined in memory)
  iex:3

{:module, Example,
 <<70, 79, 82, 49, 0, 0, 7, 144, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 241,
   0, 0, 0, 26, 14, 69, 108, 105, 120, 105, 114, 46, 69, 120, 97, 109, 112, 108,
   101, 8, 95, 95, 105, 110, 102, 111, 95, ...>>, {:run, 0}} 
iex(4)> Example.run
Exit reason: boom
:ok
iex(5)> Task.start fn -> raise "oops" end
{:ok, #PID<0.216.0>}
iex(6)> 
13:56:15.559 [error] Task #PID<0.216.0> started from #PID<0.185.0> terminating
** (RuntimeError) oops
    (stdlib 3.17) erl_eval.erl:683: :erl_eval.do_apply/6
    (elixir 1.12.2) lib/task/supervised.ex:90: Task.Supervised.invoke_mfa/2
    (stdlib 3.17) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Function: #Function<45.65746770/0 in :erl_eval.expr/5>
    Args: []
 
nil
iex(7)> defmodule Math do
...(7)> def hypot(x, y) do
...(7)> :timer.sleep(3000)
...(7)> :math.sqrt(x * x + y * y)
...(7)> end
...(7)> end
{:module, Math,
 <<70, 79, 82, 49, 0, 0, 5, 144, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 162,
   0, 0, 0, 20, 11, 69, 108, 105, 120, 105, 114, 46, 77, 97, 116, 104, 8, 95,
   95, 105, 110, 102, 111, 95, 95, 10, 97, ...>>, {:hypot, 2}}
iex(8)> task = Task.async(Math, :hypot, [3, 4])
%Task{
  owner: #PID<0.185.0>,
  pid: #PID<0.228.0>,
  ref: #Reference<0.2269777376.2268332033.214213>
}
iex(9)> Math.hypot(5, 12)
13.0
iex(10)> Task.await(task)
5.0
iex(11)> defmodule KeyValue do
...(11)> def start_link do
...(11)> Task.start_link(fn -> loop(%{}) end)
...(11)> end 
...(11)> defp loop(map) do
...(11)> receive do
...(11)> {:get, key, caller} ->
...(11)> send caller, Map.get(map, key)
...(11)> loop(map)
...(11)> {:put, key, value} ->
...(11)> loop(Map.put(map, key, value))
...(11)> end
...(11)> end
...(11)> end
{:module, KeyValue,
 <<70, 79, 82, 49, 0, 0, 7, 32, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 207,
   0, 0, 0, 21, 15, 69, 108, 105, 120, 105, 114, 46, 75, 101, 121, 86, 97, 108,
   117, 101, 8, 95, 95, 105, 110, 102, 111, ...>>, {:loop, 1}}
iex(12)> {:ok, pid} = KeyValue.start_link
{:ok, #PID<0.249.0>}
iex(13)> send(pid, {:get, :hello, self()})
{:get, :hello, #PID<0.185.0>}
iex(14)> flush
{:EXIT, #PID<0.228.0>, :normal}
nil
:ok
iex(15)> send pid, {:put, :hello, :world}
{:put, :hello, :world}
iex(16)> send pid, {:get, :hello, self()}
{:get, :hello, #PID<0.185.0>}
iex(17)> flush
:world
:ok
iex(18)> Process.register(pid, :kv)
true
iex(19)> send :kv, {:get, :hello, self()}
{:get, :hello, #PID<0.185.0>}
iex(20)> flush
:world
:ok
iex(21)> {:ok, agent} = Agent.start_link(fn -> %{} end)
{:ok, #PID<0.259.0>}
iex(22)> Agent.update(agent, fn map -> Map.put(map, :hello, :world) end)
:ok
iex(23)> Agent.get(agent, fn map -> Map.get(map, :hello) end)
:world
iex(24)> {:ok, agent} = Agent.start_link(fn -> [1, 2, 3] end)
{:ok, #PID<0.263.0>}
iex(25)> Agent.update(agent, fn state -> state ++ [4, 5] end)
:ok
iex(26)> Agent.get(agent, &(&1 -- [2, 4]))
[1, 3, 5]
iex(27)> 

まとめ

何かの役に立てばと。

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?