Skip to content

Instantly share code, notes, and snippets.

@padde
Last active May 8, 2017 23:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save padde/a759b18bca7851e8ffaa to your computer and use it in GitHub Desktop.
Save padde/a759b18bca7851e8ffaa to your computer and use it in GitHub Desktop.
Filter a list by pattern matching in Elixir
defmodule MyEnum do
defmacro filter_matching(collection, pattern) do
quote do
Enum.filter unquote(collection), fn
unquote(pattern) -> true
_ -> false
end
end
end
end
require MyEnum
MyEnum.filter_matching [a: 1, b: 2, a: 3], {:a, _}
#=> [a: 1, a: 3]
@venkatd
Copy link

venkatd commented Dec 11, 2016

The following should work:

  defmacro find_matching(collection, pattern) do
    quote do
      Enum.find(unquote(collection), &match?(unquote(pattern), &1))
    end
  end
  defmacro filter_matching(collection, pattern) do
    quote do
      Enum.filter(unquote(collection), &match?(unquote(pattern), &1))
    end
  end
  defmacro reject_matching(collection, pattern) do
    quote do
      Enum.reject(unquote(collection), &match?(unquote(pattern), &1))
    end
  end
  defmacro any_matching?(collection, pattern) do
    quote do
      Enum.any?(unquote(collection), &match?(unquote(pattern), &1))
    end
  end
  defmacro all_matching?(collection, pattern) do
    quote do
      Enum.all?(unquote(collection), &match?(unquote(pattern), &1))
    end
  end
  defmacro count_matching(collection, pattern) do
    quote do
      Enum.count(unquote(collection), &match?(unquote(pattern), &1))
    end
  end

Because of the way macros work, this is impossible to do without a macro.

@JHKennedy4
Copy link

One other approach is to just write two functions, one that matches the true case, and another that matches the false case and just pass that function. Especially helpful if you want to negate some condition such as nil in a parameter.

  zip_rates
  |> Enum.filter(&zip_nil/1)

  def zip_nil { _zip, nil } do
    false
  end

  def zip_nil { _zip, _price } do
    true
  end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment