Should `__info__(:attributes)` accumulate multiple instances of the same attribute?

so I was using MyModule.__info__(:attributes)[:behaviour] to make sure a module implements a behaviour but when the module has 2 or more behaviour definition it has several :behaviour keys, each one with a list of just one behaviour module.
is this the intended behaviour or should we have just one key :behaviour with a list of all behaviours?

1 Like

There’s already a setting for module attributes, which controls if their values are accumulated or replaced.

2 Likes

Even more concretely: Module.register_attribute

defmodule Xyz do
  Module.register_attribute(__MODULE__, :cars, accumulate: true)

  @cars "Toyota"

  def do_stuff(), do: IO.puts("hey there")

  @cars ", "
  @cars "Hyundai"

  def show_cars(), do: IO.puts(@cars)
end

Then in iex:

iex(1)> Xyz.show_cars()
Hyundai, Toyota
:ok

Note that if you put integers they’ll be accumulated in a list. Strings however just get appended at the end of the previous value.

1 Like

actually it doesn’t fix it… sure it works for when you use the attribute again as in your example but in the __info__(:attributes) will still have 2 entries instead of just one:
for example:

defmodule Abc do
  Module.register_attribute(__MODULE__, :behaviour, accumulate: true)
  use GenServer
  @behaviour MyBehaviour
...
end

Then in iex __info__(:attributes) will be:

iex(1)> Abc.__info__(:attributes)
[vsn: [...],
behaviour: [GenServer],
behaviour: [MyBehaviour]]

I see. You can still use Keyword.get_values though.

Looks weird, I agree.
Could you elaborate more on the use case? How do you approach this check?

That’s how Erlang stores multiple attributes, which we reproduce for compatibility.

3 Likes

It was for this PR

I assumed it would accumulate, and did a wrong implementation in the first PR:

1 Like