How to read a attribute created in a macro?

For the life of me I can’t figure out how to read a attribute created in a macro:

example:

defmacro staticKV(key, value) do
  quote do
    Module.put_attribute(__MODULE__, unquote(key), unquote(Macro.escape(v)))
    def value(unquote(key)), do: <<code to read the attribute defined above>>
  end
end

I wanted to do this because I have some data files that I access a LOT (in many processes currently) and the values don’t change so I would like to not pay the cost of say loading it into ets, etc.

I have tried doing @unquote(key) but that will not compile and trying to use Module.get_attribute complains because it is not called at compile time. Any help would be greatly appreciated.

3 Likes

I should add I am on elixir 1.3.3.

1 Like

My goal here was to get the values into the literal heap space and I guess I didn’t need to mess around with setting it up as an attribute in my use case (verified via :compile.forms on the output beam data ), however if anyone has an answer to the above question it would be great to know.

1 Like

Attributes do not really persist as you expected, just putting the literal into the fun body will do it though. ^.^

A couple notes, instead of get_attribute you do want to use the @blah syntax, however you need to key it ‘outside’ of your quote because the scoping rules for the @ form are a bit wonky, so this would do it by doing the raw AST:

defmacro staticKV(key, value) do
  attr_ast = {:@, [], [{key, [], [value]}]
  attr_use_ast = {:@, [], [{key, [], nil}]}
  quote do
    unquote(attr_ast)
    def value(unquote(key)), do: unquote(attr_use_ast)
end

Or something like that (untested). But yeah as you have noticed, put the value in the def body directly, not as an attribute, and that makes it very re-usable to the system. ^.^

1 Like