Generate map pattern matching functions

I have a goal to code generate the following module

defmodule C do 
  def first(%{company_id: company_id}, user}, do: do_first(company_id, user)
  def first(%{sales_id: sales_id}, user}, do: do_first(sales_id, user)
  #... etc
end

I’d like to create a macro potentially? Or even a function where I can give it a list of those atoms, and have it delegate those arguments to the second function
i.e

defmodule C do
  use FirstMacro, [:company_id, :sales_id]  #... could be a very long list
end

I keep writing macros but am unable to figure out how to code pattern match on a map macro the quoted ast for a map is something like {:%{}, , [key: value]} but I’m not able grab value like I would in defining a function so I can’t achieve my goal here, can someone point me in the right direction kindly ^^. Thanks for any help!

my attempt on the 100th iteration looks something like this

defmodule C do
  defmacro first_list(list, user) do
    quote bind_quoted: [list: list, user: user] do
      Enum.map(list, fn x ->
        def first(unquote({:%{}, [], []}), user),
          do: do_first(:need_this_variable, user)
      end)
    end
  end
end

But I know its all wrong :frowning:

As %{foo: foo} is syntactic sugar for %{:foo => foo} the following should work:

[:company_id, :sales_id]
|> Enum.each(fn key ->
  def first(%{unquote(key) => val}, user), do: do_first(val, user)
end)

But to be honest, how is do_first/2supposed to know what kind of id you are passing in?

2 Likes

I think the idea is to filter out the wrong ids using pattern matching, I thought about this but in my elixir noob head I thought that the %{key => value} syntax was sugar for the other %{key: value}

Thank you very much sir this is exactly what I needed.

1 Like

Whats a wrong ID?

first(%{company_id: 1}, user) #=> do_first(1, user)
first(%{sales_id:   1}, user) #=> do_first(1, user)

So how does do_first/2 know whether the 1 refers to a sales_id or to a company_id?

1 Like

In my particular app it doesn’t actually matter because all of our ID’s are global UUIDS. This is an Absinthe Batching function if that makes more sense. My resolvers are calling &SomeModule.first/3

1 Like