Nested conditionals

Hey guys.

I just wrote this code with two nested ifs and it got me wondering if there is a better way. I’m still strugling with functional programming in general. I think it would be “bad” to add a third if statement inside the last else, but I can’t see how to grow a logic like this. In other languages I would probably use early returns. Thanks!

def full_route(str) do
  if has_protocol?(str) do
    str
  else
    if String.starts_with?(str, "/") do
      Application.get_env(:my_app, :url) <> str
    else
      Application.get_env(:my_app, :url) <> "/" <> str
    end
  end
end

In principle, there is nothing wrong with if statements. However, you could probably leverage pattern matching to simplify your code.

If you only have a handful of protocols, you could do something like this:

def full_route("http://" <> url), do: "http://" <> url
def full_route("https://" <> url), do: "https://" <> url
def full_route("/" <> path), do: do_full_route(path)
def full_route(path), do: do_full_route(path)

defp do_full_route(path), do: Application.get_env(:my_app, :url) <> "/" <> str

Alternatively, something like the following would also work:

def full_route(url), do: do_full_route(url, has_protocol?(url)

defp do_full_route(url, has_protocol?)
defp do_full_route(url, true), do: url
defp do_full_route(path, _) do
  Application.get_env(:my_app, :url)
  |> URI.merge(path)
  |> URI.to_string()
end

As you see, the possibilities are endless :wink:

2 Likes

Wow, I didn’t think pattern matching could be a solution here. Now I see. Thanks for the help :smiley:

Your example as cond:

def full_route(str) do
  cond do
    has_protocol?(str) -> str
    String.starts_with?(str, "/") -> Application.get_env(:my_app, :url) <> str
    true -> Application.get_env(:my_app, :url) <> "/" <> str
  end
end

Although this pattern breaks down a bit when you have many branches ‘inside’ of many branches. ^.^;

3 Likes

Also see this thread:

1 Like

Thanks for the help. cond seems to fit better in this example. I’ll definetly read the thread, thanks :slight_smile:

Just to make sure we are using the correct terminology. There are no statements in elixir, only expressions.

The important difference is, that a statement does not return anything while the expression does.

4 Likes