monkeyUser
monkeyUser

Reputation: 4671

Stop the Chain in pipe operator

I have tre functions like this

check_file(url) |>test |> foo

check_file return

{:ok,_} or {:error,_}

I have Two function for pattern matching

  def test({:ok,_}) do
     IO.puts "ok";
  end

  def test({:error,_}) do
     IO.puts "KO, debug and stop!";
  end

If I got :error I don't want to call my last function (foo) but I'd like to show an error in Debug

Can I do This ?

Upvotes: 1

Views: 1255

Answers (5)

Daniel
Daniel

Reputation: 3027

I've landed on this years after the question was asked. But, maybe I can offer my 2 cents just so that if someone else is looking for an alternative to this issue can have another point of view.

Raising an error indeed does the trick. If you're not too into raise/rescue then you can try:

return_value =
  case check_file(url) |> test() do
    {:ok, valid_value} -> foo(relevant_value)
    {:error, value_after_test} -> value_after_test
  end

For this to be possible it will require that your functions return values can be used for further piping or as final return value, kind of what people do with a socket instance in phoenix. An approach to make it even simpler to read and follow is to create structs that can be passed into the pipes and have its values set/"changed" within those

Upvotes: 0

denis.peplin
denis.peplin

Reputation: 9841

What is not mentioned in other answers, is that you can raise some specific error in test function and then catch it in whatever code wraps in your pipe. Only this way you can truly stop any arbitrary long pipe.

But I wouldn't do it. I'd rather code my program in the way I don't need to stop a pipe by raising an error.

Upvotes: 0

Pfitz
Pfitz

Reputation: 7344

You can use the with statement in elixir like this

with {:ok, file} <- check_file(url) do
    file |> foo |> foo
else 
  IO.puts "KO, debug and stop!"
end

This is especially useful if test returns an {:ok, something} tuple too. Then you can expand the with

If you only have the possibility for an error at the beginning in your check_file(url) method you can do an simple solution like this:

def test({:ok,file}) do
   IO.puts "ok";
   do_your_stuff_with_the_file()t |> foo
end

def test({:error,_}) do
     IO.puts "KO, debug and stop!";
  end

Upvotes: 2

Koziołek
Koziołek

Reputation: 2874

Probably the easiest way is to add support to {:error, _} pattern to function foo:

  def foo({:ok,_}) do
     IO.puts "do the stuff";
  end
  def foo({:error,_}), do: {:error, []}

but in this kind of solution you need to return {:error} from test.

Upvotes: 0

NoDisplayName
NoDisplayName

Reputation: 15736

Just use a simple case instead:

case check_file(url) do
  {:ok, file} ->
    IO.puts "ok"
    foo(file)
  {:error, _} ->
    IO.puts "KO, debug and stop!"
end

Upvotes: 0

Related Questions