Defdelegates with same arity but different argument name for different argument types

I have a module with a function with two implementations using pattern matching:

def agent_registered(%Event{} = event) do
  ...
end

def agent_registered(agent_id) do
  ...
end

My application’s main module contains only defdelegates to a number of “implementation” modules.

Someone trying to call a function from the main module can use the auto-complete feature of iex or the IDE to see the arguments it expects, which is nice. However, in the case of that agent_registered function I can’t include two defdelegates, one for each case, as it’s the same function:

This is “wrong” (a warning is displayed for the second line):

  defdelegate agent_registered(event), to: AgentRegistered
  defdelegate agent_registered(user_id), to: AgentRegistered

This is fine, but then the argument name must cater for all the possibilities:

  defdelegate agent_registered(event_or_user_id), to: AgentRegistered

I tried adding @spec to the actual function implementation informing the possible argument types but iex and IDE keeps showing the argument name as in the defdelegate.

Have you ever had to deal with such scenario? Should I simply have different functions for different arguments instead of pattern matching in this case? Should I go for def instead of defdelegate and bring the pattern matching to the main module?

Thanks!

1 Like

I think it’s fine to delegate to a function with multiple heads and to just use an argument name that is clear. The name event_or_user_id is pretty obvious. As an aside, I wonder if you might consider whether it is more explicit at the callsite to have separate function names like agent_registered and agent_registered_by_id. Sometimes it’s nice having a function that can handle either a struct or an ID. Other times it can lead to a lack of clarity of what you’re dealing with and a whole bunch of functions needing to handle both data types rather than just always sticking with one or the other.

5 Likes