Nested conditionals

Nested conditionals are a far bigger problem in other languages and usually tend to be caused by having functions that are just too long and should already be split up but there are times when these come up and it’d be nice to have a concise way of dealing with them.

An example could be something like this

defmodule Example do def authorised?(user) do

case UserAuthenticator.authorised?(user) do

{:ok, _user} ->

true

{:error, _user} ->

case LegacyUserAuthenticator.authorised?(user) do

{:ok, _user} ->

true

{:error, _user} ->

false

end

end

end end

Not terribly elegant piece of code and slightly tricky to read as well. Imagine if instead of returning simple boolean we’d execute some longer piece of logic instead 😓

We could split up the authorised?/1 function to get rid of the nesting by doing something like this

def authorised?(user) do

case UserAuthenticator.authorised?(user) do

{:ok, _user} ->

true

{:error, _} ->

legacy_authorized?(user)

end

end defp legacy_authorized?(user) do

case LegacyAuthenticator.authorised?(user) do

{:ok, _user} ->

true

{:error, _} ->

false

end

end

Hooray no more nesting 🙌 And by using the techniques from earlier on in this series we could eliminate the conditionals altogether to get something like this

def authorised?(user) do

user

|> UserAuthenticator.authorised?()

|> check_authorised()

end def check_authorised({:ok, _}), do: true

def check_authorised({:error, user}) do

user

|> LegacyAuthenticator.authorised?()

|> check_legacy()

end def check_legacy({:ok, _}), do: true

def check_legacy(_), do: false

This is nice when you have nesting in both branches of the initial conditional as it allows you to split all of that up across lot of little functions.

Fortunately with our example we only have a nested conditional in one of the branches which allows us to look at an alternative using the the with statement

def authorised?(user) do

with {:error, _} <- UserAuthenticator.authorised?(user),

{:error, _} <- LegacyAuthenticator.authorised?(user) do

false

else

{:ok, _} -> true

end

end

😮 😍