Blog Post: 10 Elixir gotchas

Another gotcha with module attributes is that each reference injects the value, which can increase disk & mem usage. For example:

defmodule Foo do
  @x Enum.to_list(1..1_000_000)

  def foo, do: @x
  def bar, do: @x
end

Here we inject two identical large lists in the code, and the resulting file is 6 MB.

In contrast, the following code:

defmodule Foo do
  def foo, do: x()
  def bar, do: x()

  defp x, do: unquote(Enum.to_list(1..1_000_000))
end

produces a 4 MB beam, because the list is injected into the compiled beam only once.

In addition, I consider the 2nd version more flexible, because the “constant” can be provided after the implementation, which I often find better than listing various constants at the top of the file.

It’s also worth mentioning that both versions produce constants, as in terms which are handled in a special way by the runtime. See here for details.

17 Likes