Created
January 16, 2016 03:17
-
-
Save danhper/7520b87d9fd88d66ad05 to your computer and use it in GitHub Desktop.
Avoiding conditional assignments in Elixir
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Waterfall do | |
def conditional_chain(value, []), do: value | |
def conditional_chain(value, [{condition, fun}|rest]) when is_function(fun) do | |
value = if condition, | |
do: apply_fun(fun, value, condition), | |
else: value | |
conditional_chain(value, rest) | |
end | |
defp apply_fun(fun, value, condition) when is_function(fun) do | |
case :erlang.fun_info(fun)[:arity] do | |
1 -> fun.(value) | |
2 -> fun.(value, condition) | |
_ -> raise ArgumentError, "function should have arity of 1 or 2" | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule WaterfallExample do | |
import Waterfall | |
def git do | |
# original code | |
command = "--git-dir=.git fetch --force" | |
if {1, 7, 1} <= git_version() do | |
command = command <> " --progress" | |
end | |
if opts[:tag] do | |
command = command <> " --tags" | |
end | |
# | |
# with waterfall | |
# | |
command = conditional_chain("--git-dir=.git fetch --force", [ | |
{{1, 7, 1} <= git_version(), &(&1 <> " --progress")}, | |
{opts[:tag], &(&1 <> " --tags")} | |
]) | |
end | |
def hex_conn do | |
# original code | |
if ip = List.first get_req_header(conn, "x-forwarded-for") do | |
conn = %{conn | remote_ip: ip(ip, conn.remote_ip)} | |
end | |
if proto = List.first get_req_header(conn, "x-forwarded-proto") do | |
conn = %{conn | scheme: scheme(proto, conn.scheme)} | |
end | |
conn | |
# | |
# with waterfall | |
# | |
conn = conditional_chain(conn, [ | |
{get_first_header(conn, "x-forwarded-for"), &(%{&1 | remote_ip: ip(&2, &1.remote_ip)})}, | |
{get_first_header(conn, "x-forwarded-proto"), &(%{&1 | scheme: scheme(&2, &1.scheme)})} | |
]) | |
end | |
def httpoison do | |
# original code | |
if Keyword.has_key?(options, :params) do | |
url = url <> "?" <> URI.encode_query(options[:params]) | |
end | |
url = process_url(to_string(url)) | |
# | |
# with waterfall | |
# | |
url | |
|> conditional_chain([{options[:params], &(&1 <> "?" <> URI.encode_query(&2))}]) | |
|> to_string | |
|> process_url | |
end | |
def phoenix do | |
# original code | |
path = Keyword.get(opts, :path) | |
if path, do: path = Plug.Router.Utils.split(path) | |
alias = Keyword.get(opts, :alias) | |
if alias, do: alias = Atom.to_string(alias) | |
# | |
# with waterfall | |
# | |
path = conditional_chain(nil, [ | |
{Keyword.get(opts, :path), fn {_, path} -> Plug.Router.Utils.split(path) end} | |
]) | |
alias = conditional_chain(nil, [ | |
{Keyword.get(opts, :alias), fn {_, alias} -> Atom.to_string(alias) end} | |
]) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment