FizzBuzz in recursion?

I’m overthinking FizzBuzz in Elixir, refactoring everything possible Elixir way.

Now I’m trying to find a recursive way to put an IO list together so it will result in ["Fizz", ["Buzz"]]. But I’m quite stuck, recursion is difficult to grasp. So I’ve decided to ask smarter people.

defmodule FizzBuzz do
  ...

  def change(num) do
    # Recurse in with an integer in closure
    # Recurse out leaving string each step
  end

  defp name_multiple(num) when rem(num, 3) == 0, do: "Fizz"
  defp name_multiple(num) when rem(num, 5) == 0, do: "Buzz"
  defp name_multiple(_), do: ""
end

I’m not asking for the simpler solutions of FizzBuzz. I want to join FizzBuzz instead of returning them separately, so it’s more extensible. I also tried to use multi-clause functions and guards as much as I can.

My previous solution is

defmodule FizzBuzz do
  @moduledoc """
  Name multiples. 

    * Multiples of 3 => "Fizz"
    * Multiples of 5 => "Buzz"

  Concatenates when many are applicable.

    * Multiples of 3 and 5 => "FizzBuzz"

  Unapplicable numbers remain intact.
  """

  @spec list(integer) :: list
  def list(max) when is_integer(max), do: list(1..max)

  @spec list(Enumerable.t()) :: list
  def list(enum), do: Enum.map(enum, &change/1)

  @spec change(integer) :: integer | String.t()
  def change(num) do
    num
    |> prefer(fizz(num))
    |> prefer(buzz(num))
  end

  defp prefer(old, new) when not new, do: old
  defp prefer(old, new) when not is_binary(old), do: new
  defp prefer(old, new), do: old <> new

  defp fizz(num) when rem(num, 3) == 0, do: "Fizz"
  defp fizz(_), do: false

  defp buzz(num) when rem(num, 5) == 0, do: "Buzz"
  defp buzz(_), do: false
end