计算函数中的模块常量

时间:2017-02-09 07:36:19

标签: elixir

我想将一个模块常量的繁重计算放入一个单独的函数中,但这会失败:

defmodule Test do
  @test calc_constant()

  defp calc_constant do
    # Calculation heavy task like building a translation table
  end
end

我可以以某种方式做到这一点而无需在模块顶部编写整个计算吗?

1 个答案:

答案 0 :(得分:3)

是的,你可以,但你应该把这个功能放在其他模块中。

iex(1)> defmodule A, do: def calc, do: 42
{:module, A, <<70, 79, ...>>, {:calc, 0}}

iex(2)> defmodule B do
...(2)>   @a A.calc()
...(2)>   def a, do: @a
...(2)> end
{:module, B, <<70, 79, ...>>, {:a, 0}}

iex(3)> B.a
42

原因是:@var声明在编译阶段完全展开。虽然在同一模块中具有该功能,但您会遇到鸡蛋问题。

旁注:如果有一个常量需要声明,那么另一种方法是提供一个模块,在模块中声明__using__宏和Kernel.use/2这样:

defmodule HeavyConstants do
  defmacro __using__(_opts) do
    quote bind_quoted: [test1: heavy_calc1(), ...] do
      @test1 test1
      @test2 test2
      ...
      @testN testN
    end
  end
end

defmodule Test do
  use HeavyConstants

  # here you have all `N` `@test{1,2,...N}` on hand
end