2017-02-09 5 views
0

Я хотел бы поставить тяжелый расчет для постоянная модуля в отдельную функцию, но это не удается:Вычислить модуль постоянная в функции

defmodule Test do 
    @test calc_constant() 

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

Могу ли я какое-то образом сделать это без необходимости писать весь расчет на в верхней части моего модуля?

ответ

2

Да, вы можете, но вы должны поместить функцию внутри другой модуль.

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 декларации в полной мере расширили на компиляции этапе. Имея функцию внутри того же модуля, вы испытываете проблему с куриным яйцом.


Sidenote: если один имеет много постоянных декларировать, наоборот должен был бы обеспечить модуль, который объявляет __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