minhajuddin

minhajuddin

Usage of {:ok, result} / :error vs {:some, result} / :none

Rust has a very nice semantics for Option<T> and Result<T,E> These two have similar uses but have a clear distinction about expectations. Option is used when the returned value can be Some<T> or None whereas Result<T,E> is used when the returned value can be an Ok(T) or an Err(E). In Erlang and Elixir we usually see a return value of {:ok, result} or an {:error, error}, this makes sense when there are 2 possible outcomes success and a failure. However, in some cases we expect value to be present or absent, in those cases a tuple containing {:some, result} or a an atom :none seems more expressive. However there is also the possiblity of using result and nil if the result is not present. Using {:some, result} / :none will make the receiver handle both the scenarios and seems like a good way to write code. However, I haven’t seen a lot of elixir code which does this or a variation of this. I’d love to hear how you guys write these type of functions.

Most Liked

OvermindDL1

OvermindDL1

The Erlang ecosystem (and thus much of Elixir’s) uses:

{:ok, result} / :error
– or –
{:ok, result} / {:error, reason}
– or –
:ok / {:error, reason}
– or –
:ok / :error

Depending on what information needs to be returned. Consequently I’m a fan of the Exceptional Elixir Package as it wraps all of the above, and exceptions, and other things all into a single interface that is wonderfully easy to pipe around. ^.^

rvirding

rvirding

Creator of Erlang

I think the important thing is that irrespective of exactly which alternative is chosen that it is easy to pattern match on. So when you do want to test the alternatives you can just use case

case some_function(1) do
  {:ok,val} -> do_yes(val)
  {:error,err} -> do_no(err)
end

This is possible in most cases but what is also very practical that you can just match against the success case else have the system generate an exception if no match:

{:ok,val} = some_function(1)

This case is often forgotten which can complicate its usage.

michalmuskala

michalmuskala

I don’t agree that always piping everything is a good way. While it might be very easy to write, I find the given examples nearly completely illegible. They are very “dense” in behaviour and many different things are occurring at once. Treating different things, differently is not always a bad thing.

Going back to the original question about {:some, value} | :none, I’m not sure I see any difference with the currently used {:ok, value} | :error - it behaves exactly the same in all occurrences. The only difference is the names, but I’m not sure it’s worth going against the established convention in the entire platform (both Erlang and Elixir), just to have a slightly better name.

jeffdeville

jeffdeville

I agree, but I don’t know that this needs to be an either/or kind of decision. What about:

{:ok, result}
:none
{:error, error}

The with/do/else pattern I feel encourages more readable response atoms. I wound up with this recently:

with(
      client_ip = get_client_ip(request_ip, params),
      {:ok, location} <- Geoip.lookup_ip(client_ip),
      true <- should_search?(location, parse_exclusion_zone(params)),
      query = build_search_query(%SearchQuery{}, location, params),
      {:ok, results} <- NHSearch.search(query),
      Analytics.track(results, client_ip, "api", "search_results")
) do
      json conn, results
else
  {:error, :location_not_found} ->
    Logger.error("Unable to find the location for: #{get_client_ip(request_ip, params)}")
    # Need to make this an error message of some sort to explain what's going on.
    json conn, []
  :user_in_exclusion_zone ->
    Logger.info("User is too close to the exclusion box")
    # Need to make this an error message of some sort to explain what's going on.
    json conn, []
  other ->
    Logger.error(inspect(other))
    json conn, []
end

should_search could have just returned false, but with the with() pattern, I instead returned :user_in_exclusion_zone to make the code less brittle and easier to read.

Qqwy

Qqwy

TypeCheck Core Team

I’ve also seen code where people use [result] if there is a result, and [] if there is none.
Lists are of course a more general way of Rust’s Option<T> or Haskell’s Maybe type, as besides no result and one result, they might also contain two, three, etc. results.

Where Next?

Popular in Questions Top

Fl4m3Ph03n1x
Background Let’s assume I have a typical GenServer that receives messages as requests, does some operation in a DB and returns responses....
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
Codball
Mix format works fine if run from the cmd. I’ve followed this to facilitate the implementation into VSC which involves downloading an ext...
New
idi527
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir iex(2)...
New

Other popular topics Top

SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
magnetic
Hey :wave:t3: Elixir community, I’ve been learning Elixir, and working on some side projects. My editor of choice is VSCode, and althoug...
New

We're in Beta

About us Mission Statement