ImNotAVirus
`Module.delete_attribute/2` doesn't reset `accumulate: true`
Today I encountered an weird behavior when I tried to change the accumulate option for a module attribute.
I would like to know if this behavior is intended since the documentation does not mention it.
In summary the steps are:
- Create a module attribute with the
accumulate: trueoption - Delete the module attribute
- Recreate it with the
accumulate: falseoption - Try to assign values, they will still be accumulated
Here is an example :
defmodule ModuleDeleteTest do
# 1/ Define a module attribute with accumulate: true
Module.register_attribute(__MODULE__, :attribut, accumulate: true)
# 2/ Then delete and recreate the module attribute but with accumulate: false
Module.delete_attribute(__MODULE__, :attribut)
Module.register_attribute(__MODULE__, :attribut, accumulate: false)
# Unfortunately, the accumulate: true flag is still present
@attribut :foo
@attribut :bar
# > CURRENT attribut value: [:bar, :foo]
IO.inspect(@attribut, label: "CURRENT attribut value")
end
On this example I was expecting@attribut to be equals to :bar at the end.
After examining the Elixir source code, I noticed that delete_attribute/2 with accumulate: true does remove the attribute from the bag but not from the set. As a result, the set still contains the accumulate: true flag.
Here here a quick fix:
defmodule ModuleFix do
def delete_attribute(module, key) do
{set, _bag} = :elixir_module.data_tables(module)
# Here bag is clean by Module.delete_attribute/2
Module.delete_attribute(module, key)
# But you also need to clean the set or the module attribute
# still have the :accumulate flag set
:ets.delete(set, key)
end
end
defmodule ModuleDeleteTestFix do
# 1/ Define a module attribute with accumulate: true
Module.register_attribute(__MODULE__, :attribut, accumulate: true)
# 2/ Then delete and recreate the module attribute but with accumulate: false
ModuleFix.delete_attribute(__MODULE__, :attribut)
Module.register_attribute(__MODULE__, :attribut, accumulate: false)
# Now, module attribute is properly reset
@attribut :foo
@attribut :bar
# > FIXED field value: :bar
IO.inspect(@attribut, label: "FIXED attribut value")
end
As said in the introduction, I don’t know if this behavior is intended and if it is, I think it should be mentioned in the doc If it’s not, I’d be happy to open an issue on Github and propose a PR.
Marked As Solved
ImNotAVirus
It’s not a bug: https://github.com/elixir-lang/elixir/issues/11635
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









