Skip to content

Instantly share code, notes, and snippets.

@topherhunt
Last active October 18, 2019 06:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save topherhunt/81d81a7b66d061dd600dc85c8b67bec7 to your computer and use it in GitHub Desktop.
Save topherhunt/81d81a7b66d061dd600dc85c8b67bec7 to your computer and use it in GitHub Desktop.
Four approaches to expressing nested logic
defmodule Sample do
#
# VERSION 1
# The naive approach: just nest the if/else statements. Pretty readable.
#
def custom_block(project, label) do
# ... validations ...
if project do
if block = Enum.find(project.custom_blocks, & &1.label == label) do
raw block.body
else
default_block(label)
end
else
default_block(label)
end
end
#
# VERSION 2
# I think this is what "with" statements are for, let's try that. Feels clunky and redundant though.
#
def custom_block(project, label) do
# ... validations ...
with true <- project != nil,
block <- Enum.find(project.custom_blocks, & &1.label == label),
true <- block != nil do
raw block.body
else
default_block(label)
end
end
#
# VERSION 3
# Pattern-matching to reduce the verbosity of the "with" statement. Still feels weird.
#
def custom_block(project, label) do
# ... validations ...
with %Project{} <- project,
%CustomBlock{} = block <- Enum.find(project.custom_blocks, & &1.label == label) do
raw block.body
else
default_block(label)
end
end
#
# VERSION 4
# Helper function with 2 signatures lets me get rid of the nestedness in the main function. Psew.
#
def custom_block(project, label) do
# ... validations ...
if block = find_block(project, label) do
raw block.body
else
default_block(label)
end
end
defp find_block(nil, label), do: nil
defp find_block(proj, label), do: Enum.find(proj.custom_blocks, & &1.label == label)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment