Hacker News new | ask | show | jobs
by karmakaze 864 days ago
Isn't there a way of piping the ok results through? e.g.

  data
  |> call_service
  |> an_ok_unwrapper(decode)
  |> an_ok_unwrapper(store_in_db)
Or is `with` the way of doing this for ok/error results?
2 comments

`with` is more widely used, i think, but there's also `Kernel.then/2`:

    data
    |> call_service
    |> then(fn {:ok, decode} -> decode_file(decode) end)
    |> then(fn {:ok, file} -> store_file(file) end)

your solution also works if you define the function headers with a pattern match against the tuple, but then you have this extra function hanging around. Feels like a style thing more than anything else.
This approach is not equivalent since it uses a strict match in the function head inside `then`. It will raise a `FunctionClauseError` if a value not matching `{:ok, _}` is passed in.
I mean, yes, you're right that the failure mode of the `then/2` approach works differently than `with`. I think most semi-experienced elixir devs would recognize that the function used with `then/2` needs to have a pattern that matches expected returns—as does `with/else` if you want to be able to continue on the happy path of your program.

For those that don't realize that, caveat lector.

If that's the behavior desired, experienced Elixir devs would use the match operator since it's more conventional, requires fewer characters, and eliminates multiple unnecessary function calls. The thread was about monadic transformation operations similar to `and_then` on Result and Option in Rust or Promise#then in JavaScript.
Doing it with `with` is definitely the community standard. There are attempts like https://github.com/vic/ok_jose to make it more like "do" notation.