Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

What's the equivalent in elixir for something like this?

    func do(a Param) (res Result, err error) {
        var aPrime T
        if aPrime, err = getResource(a); err != nil && err == RecoverableError {
            aPrime = definitelyNoErrorAlternativeGetResource(a)
        }
        var aPrimePrime T
        ... // many more steps
        return doSomething(aPrimePrimePrime)
    }


What happens with this code when err isn't recoverable?

you can manage it a few ways in Elixir, struct matching is one:

  def perform(param) do
    res =
      case get_resource(param) do
        {:ok, val} -> val
        {:error, %RecoverableError{alternative_value: val}} -> val
      end

    do_more_things(res)
  end


Thought I'd show it in Java for comparison's sake:

  Result do(Param a) throws Exception {
    T aPrime;
    try { aPrime = getResource(a); } catch (RecoverableError e) {
      aPrime = definitelyNoErrorAlternativeGetResource(a);
    }
    T aPrimePrime;
    ... // many more steps
    return doSomething(aPrimePrimePrime);
  }


this was really hard to read. let's give it a shot, though.

    @spec my_fn(a::input_type)::{:ok, res::result_type} | {:error, any}

    def my_fn(a) do
      a
      |> get_resource
      |> case do
        {:ok, result} -> result 
        {:error, :recoverable} -> get_alt_resource(a)
        err = {:error, :reallybad} -> throw err
      end
      |> many_more_steps_might_have_similar_pattern

    catch err
      err
    end
However what you presented seems to me to be an antipattern. Sometimes code clarity trumps terseness; in this case the results from get_resource and get_alt_resource are categorically identical. If we are allowed to refactor to be actually sane code and not require everything to be in a single function:

    def my_fn(a) do
      with {:ok, res1} <- resource_wrapper(a),
           {:ok, res2} <- next_step(res1), ...
      case
        #handle errors here.
      end
    end

    @doc """
    fetches resources of type `your-favorite-type` which
    can either come from `get_resource` or `get_alt_resource`
    """
    def resource_wrapper(a) do
      case get_resource(a) do
        ok = {:ok, a} -> ok
        {:error, :recoverable} -> 
           get_alt_resource(a)
           # note with this code if alt_resource 
           # gives you an error tuple you are still 
           # good to go
        err = {:error, :fatal} -> err
      end
    end
seems much more sane




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: