2015-09-25 57 views
1

我希望在理解這裏發生的一些事情方面有所幫助,並且如果它是一種正確的/非臭的方式來做事情,這將成爲次要的想法。使用宏替換地圖條目

我有自己的文件兩個模塊:

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) 

我得到的預期值...對我好:-)。

這不工作直接MapB的定義,如果我「插入」

ModuleA.mapA_lookup(:a) 

(梁雲智力和我的ExUnit測試超時)。因爲在我的代碼中,在現實生活中,我使用地圖來定義ASN1類型(MapA)和派生類型(MapB) )。

所以問題(S)是/是:

爲什麼和怎麼做的宏定義工作? (我知道我們正在擺弄AST,但在這種情況下如何讓我的大腦痠痛)

有沒有更好的模式來達到我的目標?

感謝您的任何幫助。

+0

順便說一句,我沒有列出在我的答案,但我只是試着用Elixir 1.1.0和Erlang 18.1。我不相信這個版本會有很大的不同,但是如果你使用的是舊版本的Elixir,你可能想把它添加到你的問題中。 –

+0

是的好主意。運行1.05和erlang 18. – Englishbob

回答

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 
+0

感謝您的回覆。我已經嘗試過你的代碼版本(這是我的初始解決方案),但正如我所說的,當我至少從單元測試運行代碼時,它們會超時,並且類似於遞歸出錯時光束似乎很忙。 – Englishbob

+0

順便說一句,你是正確的。應該是is_atom(編號) – Englishbob

+0

然後,我猜這是單元測試的一些問題。上面的代碼工作得很好。也許你想添加一些關於單元測試的細節或創建一個單獨的問題。 –