The most idiomatic way to call fb () is only if fa () succeeds

I have two functions, I want to run step_1, and then run step_2, only if step_1ok. What is the most functionally idiomatic way to structure this code? Nesting operations caseseem ugly, but I'm not sure how to do this, except if, to make matters worse.

defmodule Test do
  def step_1 do
    IO.puts "Step 1"
    :error
  end

  def step_2 do
    IO.puts "Step 2"
    :ok
  end

  def do_something_case do
    case step_1 do
      :ok ->
        case step_2 do
          :ok -> {:ok}
          :error -> {:error, :step_2}
        end
      :error -> {:error, :step_1}
    end
  end

  def do_something_if do
    r1 = step_1
    if r1 == :ok
      r2 = step_2
      if r2 == :ok
        :ok
      else
        {:error, :step_2}
      end
    else
      {:error, :step_1}
    end
  end
end
+4
source share
1 answer

A common way to solve this problem (without a monad library) is to match patterns by function arguments and combine them.

defmodule Test do
  def step_1 do
    IO.puts "Step 1"
    :error
  end

  def step_2(:ok) do
    IO.puts "Step 2"
    :ok
  end
  def step_2({:error, _reason} = error) do
    error
  end

  def do_something_pipeline do
    step_1
    |> step_2
  end
end
+8
source

Source: https://habr.com/ru/post/1612197/


All Articles