6
votes

What is the canonical way of making a "const array" with random access in Elixir language? (For example one used in CRC calculations, or AES s-boxes)

From Erlang background I assume, that "array" itself should be a tuple, as access via elem/2 / element/2 seems to be O(1) (function BIF_RETTYPE element_2(BIF_ALIST_2) in erts/emulator/beam/bif.c).

But what about storage scope, as Erlang/Elixir has no globals? My nose says @module_attribute would be the place, but I'm not quite sure where and when @attributes are expanded.

There is a known Erlang problem: when you -define(LARGE_LIST,[...]) in module and then use ?LARGE_LIST in functions. The value is re-constructed at each function call. Solution was to construct it once at application start and pass to functions needing it as one of parameters.

Does @module_attribute of Elixir solve this problem or is it treated as fancy macro expansion? I've read official docs on module attributes, but I'm still confused.

1

1 Answers

7
votes

From the documentation, it seems like Elixir module attributes work like Erlang module attributes, i.e. they are module metadata which can be retrieved by Module:module_info(Attributes). This eventually goes into the function attributes_for_module in beam_load.c, which as far as I can see copies the data every time it is accessed. Thus, a module attribute wouldn't be suitable for a large piece of frequently accessed data.

Instead, I would write a function that takes no arguments and just returns the tuple. The tuple will be compiled into the module's constant pool, so it won't be reconstructed every time the function is called; the function essentially returns a reference to constant data. This is described in the "Constant Pool" section in the Erlang Efficiency Guide.