使用宏替换映射条目

时间:2015-09-25 13:59:15

标签: elixir

我很感激在理解这里发生的事情方面提供了一些帮助,如果它是一种正确/无臭的做事方式,我将非常感谢。

我在自己的文件中有两个模块:

defmodule ModuleA do
   def mapA do
    %{a: 1, 
      b: 2,
      c: 3,
      d: 4
     }
   end
   def mapA_lookup(id) when is_atom(i) do
    Dict.get(mapA, id)
   end
end

defmodule ModuleB do
   import ModuleA

   defmacro a_value_from_MapA do
     quote do ModuleA.mapA_lookup(:a) end
   end

   def mapB do
    %{e: a_value_from_MapA, #needs to have same value as :a
      f: 5,
      g: 6
     }
    end
  def mapB_lookup(id) when is_atom(id) do
    Dict.get(mapB, id)
  end
end

现在我使用

mapB_lookup(:e)

我得到了预期的价值......对我有好处: - )。

如果我"插入"

,这不起作用
ModuleA.mapA_lookup(:a) 

直接在MapB的定义中(BEAM是精神上的,我的ExUnit测试超时)。

我想要做的事情是非常清楚MapB中值的来源,因为在我的代码中,在现实生活中,我使用map来定义ASN1类型(MapA)并派生类型(MapB)。

所以问题是:

为什么以及如何使用宏定义? (我知道我们正在摆弄AST,但在这种情况下如何让我的大脑疼痛)

是否有更好的模式来实现我的目标?

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

您是否复制了文字代码?因为我认为这是一个错误:

def mapA_lookup(id) when is_atom(i) do
    Dict.get(mapA, id)
   end

我认为你的意思是:

   def mapA_lookup(id) when is_atom(id) do
    Dict.get(mapA, id)
   end

请注意is_atom保护条款。

当然如果你复制了错误的代码,那就别管了。

顺便说一句,我严重怀疑你需要一个宏来做到这一点。如果我有机会,我会看看是否可以将一些演示代码合并到一起并将其附加到此答案中。

编辑:

是的,事实上,我认为您的代码几乎是正确的,但您绝对不需要宏。这对我有用:

defmodule ModuleA do
   def mapA do
    %{a: 1, 
      b: 2,
      c: 3,
      d: 4
     }
   end
   def mapA_lookup(id) when is_atom(id) do
    Dict.get(mapA, id)
   end
end

defmodule ModuleB do
   import ModuleA

   def mapB do
    %{e: mapA_lookup(:a), #needs to have same value as :a
      f: 5,
      g: 6
     }
    end
  def mapB_lookup(id) when is_atom(id) do
    Dict.get(mapB, id)
  end
end