Getting warning: inside guards requires an explicit step

Hi!

I need help understanding the following warning message:

warning: srs..srs + len - 1 inside guards requires an explicit step, please write srs..srs + len - 1//1 or srs..srs + len - 1//-1 instead

Which is caused by this:

  defp compute_over_range(number, [[drs, srs, len] | _])
       when number in srs..(srs + len - 1) do
    compute_over_range(number - srs + drs, [])
  end

Here’s the whole file: (my solution for day 5, part 1 of AOC 2023)

defmodule Day5 do
  def solve(input, 1) do
    input
    |> parse()
    |> run_seeds()
    |> Enum.min()
  end

  defp run_seeds([seeds | maps]) do
    Enum.map(
      seeds,
      fn seed ->
        run_trough_maps(seed, maps)
      end
    )
  end

  defp run_trough_maps(number, []), do: number

  defp run_trough_maps(number, [map | other_maps]) do
    number
    |> convert(map)
    |> run_trough_maps(other_maps)
  end

  defp convert(number, []), do: number

  defp convert(number, [range | map]) do
    number
    |> compute_over_range(range)
    |> convert(map)
  end

  defp compute_over_range(number, []), do: number

  defp compute_over_range(number, [[drs, srs, len] | _])
       when number in srs..(srs + len - 1) do
    compute_over_range(number - srs + drs, [])
  end

  defp compute_over_range(number, [_ | ranges]) do
    compute_over_range(number, ranges)
  end

  defp parse(input) do
    [seeds | maps] =
      input
      |> String.split("\n\n")
      |> Enum.map(fn paragraph ->
        paragraph
        |> String.split(":")
        |> tl()
        |> hd()
        |> String.trim()
        |> String.split("\n")
        |> Enum.map(fn line ->
          line
          |> String.split(" ")
          |> Enum.map(fn number -> String.to_integer(number) end)
        end)
      end)

    [hd(seeds), maps]
  end
end

Any other feedback about my code is welcome :slight_smile:

1 Like

It wants you to be explicit about how much to increment each step of the range, which is done by adding //n to the end of the Range literal:

iex> 1..6//1 |> Enum.to_list()
[1, 2, 3, 4, 5, 6]
iex> 1..6//2 |> Enum.to_list()
[1, 3, 5]
1 Like

For context, the deprecation is because implicit steps may produce negative ranges, which can cause unexpected issues.

Also, for code comments, I’d probably recommend splitting up your parse/1 a bit. There are a lot of splits, and the split |> tail |> hd is suspect.

2 Likes