Language Similarities
For the last several years, I have participated in Advent of Code, going back and forth between using languages I use day-to-day (Elixir, Ruby) and trying languages I am not as familiar with.
One year, I decided to try using Go. Among other interesting features is the capability of functions to return multiple values, rather than a single value.
For example:
val, err := strconv.Atoi(s)
s
into an integer value val
. But, since not all strings
can be successfully converted, the function can also return an error. It’s up to us to do someting (or not) with the
error, like this:
val, err := strconv.Atoi(s)
if err == nil {
// no error, so we'll do something with val
} else {
// we have an error; do things to handle it
}
Elixir has a similar pattern, using tuples containing :ok
or :error
as the first value of the tuple.
When used with a case
statement, a similar flow in Elixir would look like this:
case string_to_integer(s) do
{:ok, val} -> # the function succeeded, so do things with val
{:error, error} -> # the function failed, so handle the error
end
As I mentioned above, most of my daily work involves Elixir, Ruby, or both. Every so often, I encounter a situation
in one language where the “best” or “cleanest” (to me) solution would be something that exists in the other language.
At the time I was working Advent of Code problems with Go, I encountered a problem in a Ruby codebase where I wanted to
use Elixir’s :ok/:error
tuples, but my little bit of Go reminded me of a similar capability in Ruby.
It’s not common, as far as I’ve seen, but it’s perfectly acceptable to write a method like this:
def do_the_thing(x)
# Use x to do stuff that may fail,
# but we don't want to produce an exception
return result, error
end
result, error = do_the_thing(s)
if error
# Handle the error
else
# Handle the successful result
end
result
or error
can be null if you’re doing this, or else
you may miss something, depending on how you want to handle the returned values.