Reusing compile time code

Sorry, you are right.
It is absolutely not needed, you can get away with it by storing the value at compile time in an attribute and invoke it inside a function.

Something like this based on Michal’s code.

defmodule SportsCsvReader do
  @sports_data         :my_app
    |> :code.priv_dir()
    |> Path.join("awesome_csv.csv")
    |> File.stream!()
    |> CSV.decode!(headers: false, separator: ?;)
    |> Stream.map(&List.to_tuple/1)
    |> Stream.uniq()
    |> Enum.map(fn {sport, country, league} ->
      {String.trim(sport), String.trim(country), String.trim(league)}
    end)

  def sports_data(), do: @sports_data

  def extract_sports(sports_data) do
    sports_data
    |> Enum.map(fn {sport, _country, _league} -> sport end)
    |> Enum.filter(fn sport -> sport != "" end)
  end

  def extract_countries(sports_data) do
    sports_data
    |> Enum.map(fn {_sport, country, _league} -> country end)
  end
end

My point is that you only need to parse the CSV once, and that is at compile time.