KONDO Daisuke
KONDO Daisuke

Reputation: 304

How to define shared constant on Elixir

Can I define constant shared with modules?

Generally, we use module attribute for constant inside module. http://elixir-lang.github.io/getting-started/module-attributes.html#as-constants

If I want to make constant available to other modules, how can I do it? At first, module attribute is available just only inside module(1). I know I can use function as constant(2). But if possible, I want to define constant by dedicated form like 3.

defmodule Sample do
    # 1. module attribute(available only inside module)
    @private_const_value 1
    # 2. function as constant(possible in any rate)
    def const_value_func, do: 3
    # 3. ideal form(but compile error)
    public_const_value = 2
end

defmodule Client do
    def foo() do
        IO.puts "CONST = #{Sample.@private_const_value}" # compile error
        IO.puts "CONST = #{Sample.const_value_func}"
        IO.puts "CONST = #{Sample.public_const_value}" # compile error
    end
end

postscript

I expect that constant satisfies following requirements.

Upvotes: 3

Views: 1914

Answers (2)

Vivian
Vivian

Reputation: 1639

A non-module-specific constant is generally put in config/foo.exs, and accessed by System.get_env/1 or Application.get_env/2. If you want it to be under/inside a specific module (and not just a specific application) for reasons that can't be satisfied by just giving it an appropriate name and using one of the above options... first, be sure that that's accurate and you have a good reason, because I can't think of one off the top of my head.

If you still want that, the answer is (AFAIK) just your option-2, the function. If you want a dedicated form for it, do it with a macro:

defmacro const([{name, val}]) do
  quote do
    def unquote(name) do: unquote(val)
  end
end

Then you can just do const foo: 87 in any module where you've required and imported the module with const defined in it.

Or you could define each constant as a macro instead of a function. Disadvantage: You need to require the modules. Advantage: Resolves at compile-time, like attributes do. Though functions of arity 0 that don't have side effects might do that anyway, I'm not sure but it's a reasonable optimization.

Upvotes: 5

Onorio Catenacci
Onorio Catenacci

Reputation: 15293

You also want to take a look at the Module.register_attribute function. You'd use this in conjunction with Module.get_attribute. I seem to recall something about using this as a means to share attributes across modules.

Upvotes: 0

Related Questions