3 ms·
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`
by karmakaze 3y 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?
- karmajunkie 3y ago`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.
- xanthor 3y agoThis 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.
- karmajunkie 3y agoI 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.
- xanthor 3y agoIf 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.
- ollysb 3y agoDoing it with `with` is definitely the community standard. There are attempts like https://github.com/vic/ok_jose https://github.com/vic/ok_jose to make it more like "do" notation.