2016-10-25 31 views
0

我需要我所有的模型来实现特定的协议。我现在的尝试是一个MyApp.Convert模块,这个宏定义:我怎样才能同时为多个模块定义? (宏尝试不工作)

defmodule ConvertMacro do 
    @moduledoc """ 
    All model structs need to implement the convert interface and must be added 
    here. 
    """ 

    defmacro defimpl_convert_for(modules) do 
    Enum.map(modules, fn module -> 
     quote do 
     defimpl Units.Convert, for: unquote(module) do 
      require Units 

      def to_standard_metric(struct) do 
      Units.to_standard_metric_for_struct(unquote(module), struct) 
      end 

      def to_user_data(struct) do 
      Units.to_user_data_for_struct(unquote(module), struct) 
      end 
     end 
     end 
    end) 
    end 
end 

ConvertMacto.defimpl_convert_for([MyApp.User, MyApp.Block]) 

错误:

== Compilation error on file lib/protocols/units_convert.ex == 
** (UndefinedFunctionError) function ConvertMacro.defimpl_convert_for/1 is undefined or private. Did you mean one of: 

     * defimpl_convert_for/1 

    ConvertMacro.defimpl_convert_for([UdioDb.Block]) 
    (elixir) lib/kernel/parallel_compiler.ex:117: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1 

(错误消息实际上是有点多余)

有没有办法来实现我试图去做,还是我只需要输入一切呢?

+0

你可以请包括[MCVE](http://stackoverflow.com/help/mcve)或至少包括周围的代码和错误消息?当我们不知道如何调用这个宏以及错误是什么时,很难弄清楚究竟发生了什么错误。 – Dogbert

+0

@Dogbert发布​​了带有错误 –

+0

的完整代码(请注意,您也可以将列表传递给'defimpl':https://github.com/elixir-lang/elixir/blob/03a7d744cc1ce7c3820ee60cafcf71b1bc7d5211/lib/elixir/test/elixir/protocol_test .exs#L183-L185) – Dogbert

回答

4

它实际上是因为defimpl更简单的支持它本身:

defimpl FooProtocol, for: [Foo, Baz, Bar] do 
    def protocol_function(x, y, z) do 
    @for.some_function(x, y, z) 
    end 
end 

@for模块属性允许您访问该协议是为实现该模块。你可以在这里看到例子:https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/date_time.ex#L650-L662

+0

omg我对这个语言的最大暗恋<3(并且对于我不推荐RTFM而感到羞耻) –

+0

@ o_o_o--发现utf8,Elixir值得❤❤❤而不是<3 – mudasobwa

相关问题