by Michael Lubas
Write a function in Elixir named
build_string that takes 4 arguments:
a - An integer b - An integer ops - A list of the atoms [:add, :sub, :mul, :div] in any order, max length of 10 sep - A separator, such as "-" or ","
and returns a string where a and b are calculated, in-order, together according to the list of operations, delimited by the separator value. For example:
> build_string(8, 2, [:add, :sub], ",") > "10,6" > build_string(10, 5, [:div, :sub, :mul, :add], "-") "2-5-50-15"
Here is an example of bad style:
defmodule Codex do # Bad style def build_string(a, b, ops, sep) do Enum.reduce(ops, "", fn op, acc -> acc <> sep <> Integer.to_string(calculate(a, b, op)) end) |> String.trim_leading(sep) end def calculate(a, b, op) do case op do :add -> a + b :sub -> a - b :mul -> a * b :div -> div(a, b) end end end
Focus on the
def build_string(a, b, ops, sep) do Enum.reduce(ops, "", fn op, acc -> acc <> sep <> Integer.to_string(calculate(a, b, op)) end) |> String.trim_leading(sep) end
From the start at
Enum.reduce, the accumulator is a blank string, so reduce is creating a string. It is iterating over ops, so the accumulator will be built up in steps:
> build_string(8, 2, [:add, :sub], ",") > # inside Enum.reduce > "" <> "," <> "10" > ",10" > ",10" <> "," <> "6" > ",10,6"
Then there is a call to trim the leading
sep, in this case
",". The call to
String.trim_leading/2 here is a red flag that there is a special case in the code evaluation, an additional leading separator value that should not have been introduced.
Now consider this version of
# Good style def build_string(a, b, ops, sep) do ops |> Enum.map(&calculate(a, b, &1)) |> Enum.join(sep) end
Enum.map conveys that
calculate/3 transforms every element in the list, preserving the order. Elixir provides
Enum.join, but even if it was not included, writing a function to join all the elements of the list together with a separator value makes this much more clear.
> build_string(8, 2, [:add, :sub], ",") > [10, 6] # Produced by Enum.map([:add, :sub], &calculate(8, 2, &1)) > "10,6" # Produced by Enum.join([10, 6], ",")
This avoids the problem of building up a string where the leading separator needs to be removed. The problem given may seem trivial, and it is. Making your code as easy to read as possible, by avoiding unnecessary cases, is the important point.
Paraxial.io is the only application security and compliance platform made for Elixir.
Subscribe for new posts about Elixir and Phoenix security.