less than 1 minute read

Functional Web Development with Elixir, OTP, and Phoenix (Lance Halvorsen, 2018)’ 책에서 간단한 함수 하나로 pipe operator를 끝까지 태우는 코드를 봤다. GenServer Behaviour 콜백 함수인 handle_call/3 함수의 구현이다.

def handle_call({:add_player, name}, _from, state_data) do
  with {:ok, rules} <- Rules.check(state_data.rules, :add_player) do
    state_data
    |> update_player2_name(name)
    |> update_rules(rules)
    |> reply_success(:ok)
  else
    :error -> {:reply, :error, state_data}
  end
end

defp reply_success(state_data, reply), do: {:reply, reply, state_data}

reply_success/2 함수 구현으로 파이프를 끝까지 태울 수 있다. 이걸 안 쓴다면 변수를 하나 추가해야 한다.

def handle_call({:add_player, name}, _from, state_data) do
  with {:ok, rules} <- Rules.check(state_data.rules, :add_player) do
    state_date =
      state_data
      |> update_player2_name(name)
      |> update_rules(rules)

    {:reply, :ok, state_date}
  else
    :error -> {:reply, :error, state_data}
  end
end

reply_success/2 함수를 정의하지 않고 Elixir 1.12에 추가된 then/2 매크로를 사용해도 된다.

def handle_call({:add_player, name}, _from, state_data) do
  with {:ok, rules} <- Rules.check(state_data.rules, :add_player) do
    state_data
    |> update_player2_name(name)
    |> update_rules(rules)
    |> then(&{:reply, :ok, &1})
  else
    :error -> {:reply, :error, state_data}
  end
end

pipe operator가 중간에 끊기면 섭섭하다. 한 번 쓰는 함수가 아니라 반복적으로 쓸 수 있는 함수라서 reply_success/2 함수 같은 걸 helper 모듈에 정의해 놓고 쓰는 것도 괜찮겠다.