Why is the parameter "not in use"?

defmodule App do

  def list_users do
    [
      %{id: "1", name: "José", username: "josevalim"},
      %{id: "2", name: "Bruce", username: "redrapids"},
      %{id: "3", name: "Chris", username: "chrismccord"}
    ]
  end


  def test() do
    Enum.find(list_users(), fn element ->
      match?(%{name: "Bruce"}, element)
    end)
  end
end

IO.inspect(App.test())   # %{id: "2", name: "Bruce", username: "redrapids"}

The above code has data hardcoded as the argument of the match? function, and it works as expected.

If I pass an argument (the code below) it doesn’t work. I don’t understand why.


defmodule App do
  def list_users do
    [
      %{id: "1", name: "José", username: "josevalim"},
      %{id: "2", name: "Bruce", username: "redrapids"},
      %{id: "3", name: "Chris", username: "chrismccord"}
    ]
  end

  def test(data) do
    Enum.find(list_users(), fn element ->
      match?(data, element)
    end)
  end
end


IO.inspect(App.test(%{name: "Bruce"}))

warning: variable "data" is unused (if the variable is not meant to be used, prefix it with an underscore)
  app.ex:12: App.test/1

warning: variable "data" is unused (if the variable is not meant to be used, prefix it with an underscore)
  app.ex:10: App.test/1

%{id: "1", name: "José", username: "josevalim"}

:wave:

match? is a macro that gets expanded to a case block. So match?(data, element) is the same as

case element do
  data -> true
  _other -> false
end

which means element is bound to data and then left unused.

https://hexdocs.pm/elixir/Kernel.html#match?/2

Try using match?(^data, element).

2 Likes

@wktdev however that will make no sense. You probably meant Enum.find(list_users(), fn element -> element == data end) or Enum.find(list_users(), & &1 == data) for short.

1 Like

As others have already mentioned match?/1 is a macro, where the first arguments needs to be a match pattern. What you’re attempting is passing a match pattern around, which is not supported by the beam. Match patterns are not a datatype, but a compile time construct, which can only ever be hardcoded.

You could however pass “data” around like so:

  def test(name) do
    Enum.find(list_users(), fn element ->
      match?(%{name: ^name}, element)
    end)
  end
…
IO.inspect(App.test("Bruce"))
3 Likes