Dear Clojuverse community,
Last year I started using my first functional language Elixir and this year I decided to try Clojure and write some serious amount of code in it to make a decision which I like more.
While reading Getting Closure book I started re-writing some snippets of code that I wrote in Elixir and I quickly realized that in Elixir I extensively used an interesting pattern that technically can be implemented in Clojure but I’m not sure that this would be a good idea.
In Elixir many functions return 2 element tuple {:ok, "something"}
or :error
/ {:error, :description_what_happened}
which in Clojure would look like 2 element vector [:ok, "something"]
or [:error, :description_what_happened]
.
Of course in Elixir you’re not forced to return something like that but since a lot of core functions do return it so it makes totally sense to write your own functions that return :error
instead of throw
when something is not all right.
There are a couple of reasons why Erlang/Elixir in my opinion is pushing this pattern:
-
You are not supposed to use try/catch (except when using non-native libraries). You can
throw
but you don’t use it often and if you do, the naming convention is to add “!” to highlight that the function can explode. -
You use pattern matching literary everywhere so you end up writing a lot of code like this:
case do_something(with_this) do
# you can for example just return it
{:ok, data} -> data
# or do something
{:error, :valve_is_broken} -> ...somehow handle broken valve...
# or do something with error you're not prepared for
{:error, error} -> log_this_error(error)
end
Could you please tell me does this 2 element OK/ERROR pattern have a use in Clojure?
Of course it does not have to be vector. I think a Map {:status :ok, :something "something"}
makes more sense since you can easily add keys without braking API (as mentioned in Should I use vector to return 2 or 3 pieces of information from a function?).
I think I’m also slightly confused about error handling since the Clojure answer might be to just return nil
instead of throw
.
Thank you.
Kind regards,
Allan