I always prefer function clauses instead of conditionals (if/2, case/2, cond/1) whenever possible.
defmodule TreeRecurse do
@indent 2
def print_tree(tree, indent \\ 0, acc \\ []) do
tree
|> traverse_tree(indent, acc)
|> Enum.join("\n")
|> IO.puts()
end
defp traverse_tree(leaf, indent, acc) when is_binary(leaf),
do: [indented(leaf, indent) | acc]
defp traverse_tree({leaf}, indent, acc),
do: traverse_tree(leaf, indent, acc)
defp traverse_tree({head, tail}, indent, acc) when is_binary(head) and is_binary(tail),
do: [indented(head, indent), indented(tail, indent) | acc]
defp traverse_tree({head, tail}, indent, acc) when is_binary(head),
do: [indented(head, indent) | traverse_tree(tail, indent + 1, acc)] ++ acc
defp traverse_tree({head, tail}, indent, acc) when is_binary(tail),
do: traverse_tree(head, indent + 1, acc) ++ [indented(tail, indent) | acc]
defp traverse_tree({head, tail}, indent, acc),
do: traverse_tree(head, indent + 1, acc) ++ traverse_tree(tail, indent + 1, acc) ++ acc
defp indented(input, indent) when is_number(indent),
do: ' ' |> List.duplicate(indent * @indent) |> to_string() |> Kernel.<>(input)
end


















