2017-02-15 3 views
0

私はエリクシルのメタプログラミングを研究しています。私はmacroを使ってRESTリソースを定義することができます。インターフェースは次のようになります:Eixirメタプログラミング - マクロ内でコンパイル時に利用可能なマクロを定義する

defmodule Router do 
    use Resources 

    resource "cars" 
    resource "animals" 
end 

Iまし限り動作するように、次のModuleモジュールを使用して、モジュールの属性を定義するが、私は得ることができないよう:

defmodule Resource do 
    defmacro __using__(_opts) do 
    quote do 
     Module.put_attribute __MODULE__, :stack, [1, 2, 3] 
     defmacro resource(name) do 
     stack = Module.get_attribute __MODULE__, :stack 
     Module.put_attribute __MODULE__, :stack, [name|stack] 
     end 
    end 
    end 
end 

次はしていませんコンパイル:

defmodule Domain do 
    use Resource 

    resource "foo" 

    def run do 
    IO.inspect @stack 
    end 
end 

リソース行を削除すると、[1, 2, 3]が正しく印刷されます。

resource/1マクロはrun/0から表示されます。

ルーターでコードを取得して、リソース「xxx」を呼び出すと、@stackモジュール属性のスタックに「xxx」がプッシュされますか?

答えて

1

__using__マクロ内ではなく、別の2番目のMacroを個別に定義する必要があります。最初のマクロをimportリソースに使用して、@stackの初期値を定義すると、モジュール内でresourceマクロを使用できます。

Module.get_attributeModule.put_attributeに電話する必要はなく、どこでも@stackを使用してください。

はこれを試してみてください:Domain.runを呼び出す

defmodule Resource do 
    defmacro __using__(_opts) do 
    quote do 
     import Resource 
     @stack [1,2,3] 
    end 
    end 

    defmacro resource(name) do 
    quote do 
     @stack [unquote(name) | @stack] 
    end 
    end 
end 

は今あなたに["foo", 1, 2, 3]を与える必要があります。あなたはまた、エリクシールであなた自身のDomain Specific Languagesを構築する公式ガイドを参照する必要があります。

関連する問題