Conversion from "For" to "Recursion"

Hi,

I the Dave Thomas book there is a problem which is related to pattern matching and it’s done using for loop. Is there any way we can write it using “Recursion”?

defmodule Maps do
  people = [
    %{name: "Grumpy", height: 1.24},
    %{name: "Dave", height: 1.88},
    %{name: "Dopey", height: 1.32},
    %{name: "Shaquille", height: 2.16},
    %{name: "Sneezy", height: 1.28}
  ]

  IO.inspect(for person = %{height: height} <- people, height > 1.5, do: person)
end

Output:

[%{height: 1.88, name: "Dave"}, %{height: 2.16, name: "Shaquille"}]

This is not a for loop it is a comprehension and very Elixir-/Erlang-y.

You can find a short overview on comprehensions here:

1 Like

Maybe something like this:

defmodule Maps do
  @people [
    %{name: "Grumpy", height: 1.24},
    %{name: "Dave", height: 1.88},
    %{name: "Dopey", height: 1.32},
    %{name: "Shaquille", height: 2.16},
    %{name: "Sneezy", height: 1.28}
  ]
  
  def people, do: @people

  def taller_than(people, height, acc \\ [])
  def taller_than([], height, acc), do: acc
  def taller_than([person | rest], height, acc) do
    case person.height > height do
      true -> taller_than(rest, height, [person | acc])
      false -> taller_than(rest, height, acc)
    end
  end
end

Maps.people() |> Maps.taller_than(1.5)
3 Likes

Thank you so much …

1 Like

Thats a solid solution and it make much more sense. Thank you so much.

IMHO the most intuitive way is neither list comprehension nor recursion, but Enum.filter:

Enum.filter(people, fn %{height: h} -> h > 1.5 end)
4 Likes

Thats a very Idiomatic way of solving this issue. Thanks Derek