Nao000のぶろぐ

蝶を追っている少年になりたい

「プログラミング Elixir」の 第16章の練習問題4,5の解答例

「プログラミング Elixir」の 第16章の練習問題4,5の解答例

練習問題 OTP-Server-4

  def start_link(initial_stack) do
    GenServer.start_link(__MODULE__, initial_stack, name: __MODULE__)
  end

呼び出し例

iex(2)> Sequence.Server.start_link([100, 200, 300])
{:ok, #PID<0.162.0>}

練習問題 OTP-Server-5

terminate コールバック実装例

  def terminate(_reason, state) do
    IO.puts "terminate: #{inspect(state)}"
  end

呼ばれる例

iex(6)> Sequence.Server.pop
terminate: []

04:05:12.177 [error] GenServer Sequence.Server terminating
** (MatchError) no match of right hand side value: []
    (sequence 0.1.0) lib/sequence/server.ex:42: Sequence.Server.handle_call/3
    (stdlib 3.16.1) gen_server.erl:721: :gen_server.try_handle_call/4
    (stdlib 3.16.1) gen_server.erl:750: :gen_server.handle_msg/6
    (stdlib 3.16.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message (from #PID<0.159.0>): :stack
State: [data: [{'State', "My current state is '[]', and I'm happy"}]]
Client #PID<0.159.0> is alive

    (stdlib 3.16.1) gen.erl:233: :gen.do_call/4
    (elixir 1.13.0-rc.1) lib/gen_server.ex:1027: GenServer.call/3
    (stdlib 3.16.1) erl_eval.erl:685: :erl_eval.do_apply/6
    (elixir 1.13.0-rc.1) src/elixir.erl:289: :elixir.recur_eval/3
    (elixir 1.13.0-rc.1) src/elixir.erl:274: :elixir.eval_forms/3
    (iex 1.13.0-rc.1) lib/iex/evaluator.ex:310: IEx.Evaluator.handle_eval/3
    (iex 1.13.0-rc.1) lib/iex/evaluator.ex:285: IEx.Evaluator.do_eval/3
    (iex 1.13.0-rc.1) lib/iex/evaluator.ex:274: IEx.Evaluator.eval/3
** (EXIT from #PID<0.159.0>) shell process exited with reason: an exception was raised:
    ** (MatchError) no match of right hand side value: []
        (sequence 0.1.0) lib/sequence/server.ex:42: Sequence.Server.handle_call/3
        (stdlib 3.16.1) gen_server.erl:721: :gen_server.try_handle_call/4
        (stdlib 3.16.1) gen_server.erl:750: :gen_server.handle_msg/6
        (stdlib 3.16.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3

push 時にサーバを終了させる例

  # 10以上の数値を push した場合は続ける
  def push(push) when push >= 10 do
    IO.puts "push value is 10 or more"
    GenServer.cast __MODULE__, {:stack, push}
  end

  # 10未満の数値を push した場合に終了
  def push(push) when push < 10 do
    IO.puts "push value is less than 10"
    IO.puts "exit"
    System.halt(0)
  end

  # 数値以外を push した場合に終了
  def push(push) when not is_number(push) do
    IO.puts "push value is not a number"
    IO.puts "exit"
    System.halt(0)
  end

呼ばれる例

10未満の数値を push した場合に終了

iex(2)> Sequence.Server.start_link([100, 200, 300])
{:ok, #PID<0.170.0>}
iex(3)> Sequence.Server.push(100)
push value is 10 or more
:ok
iex(4)> Sequence.Server.push(10)
push value is 10 or more
:ok
iex(5)> Sequence.Server.push(9)
push value is less than 10
/home/trial/sequence #

数値以外を push した場合に終了

iex(2)> Sequence.Server.start_link([100, 200, 300])
{:ok, #PID<0.162.0>}
iex(3)> Sequence.Server.push(10)
push value is 10 or more
:ok
iex(4)> Sequence.Server.push("example")
push value is not a number
exit
/home/trial/sequence #