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

Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
dokuzbir
Hello, I am trying to convert my lists to string without losing brackets.For start i have 3 map. They look like these buyer = %{ id: ...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
makeitrein
Hey all, just started picking up Elixir last week and am writing a scraper as a learning project. Baby step #1 is extracting the number ...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
chewm
Hi guys, nice to meet you to the whole forum, I’m new here, I’m trying to configure visual studio code for elixir, right now the intellis...
New
jc00ke
Expanding on this topic: https://forum.elixirforum.net/t/map-typespec-question/19217 Let’s say I have a map with required and optional k...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

Other popular topics Top

yurko
Here are few pieces of (common) Linux knowledge that we use for reasonably small one server apps. We use Ubuntu but this should work for ...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New

We're in Beta

About us Mission Statement