2013-12-22 66 views
3

將Erlang(或Elixir)中的元組與記錄進行匹配的模式是不好的做法?與Erlang(Elixir)中的元組相匹配的記錄模式

代碼示例:假設我們已經定義了這個模塊:

defmodule Ween do 
    defrecord TimeSpot, at: nil, tag: nil 

    def proper?({ _, _, "home"} = v), do: { true, "succeeded with: #{inspect v}"  } 
    def proper?(other),     do: { false, "failed with:  #{inspect other}" } 

    def sample, do: TimeSpot.new(tag: "home") 
end 

如果我們定義的測試如下:

defmodule WeenTest do 
    use ExUnit.Case 
    require Ween 

    test "records are tuples" do 
    case Ween.proper?(Ween.sample) do 
     { true, v }  -> IO.puts v 
          assert(true) 
     { false, v }  -> IO.puts v 
          assert(false) 
    end 
    end 
end 

它會成功。

編輯1:@parroty 這裏模式匹配測試元組的模式是爲了模擬一些「排序」鴨記錄的原因;我希望的終極的東西,應該是這樣的:

defmodule Ween do 
    defrecord TimeSpot, at: nil, tag: nil 

    def proper?([tag: "home"] = v),   do: { true, "succeeded with: #{inspect v}"  } 
    def proper?([tag: "1234"] = v),   do: { true, "succeeded with: #{inspect v}"  } 
    def proper?(other),      do: { false, "failed with:  #{inspect other}" } 

    def sample, do: TimeSpot.new(tag: "home") 
end 

所以用「標籤」字段霸菱一個「家」的價值每記錄將第一條相匹配。當然,那裏會有一些表現處罰。

回答

4

Cesarini和Thompson在他們的書中說Erlang編程永遠不要依賴記錄被實現爲元組的事實,因爲實現可能會改變。請參閱this question的接受答案。

+3

另外一個原因是,你可能要在這種情況下,直接以更改記錄定義(例如添加新字段)模式匹配將需要修改,而Parroty解決方案仍然很好。恕我直言,這是使用記錄而不是元組的原因,所以這就是爲什麼不使用與記錄直接模式匹配很重要的原因。 – Pascal

+0

實際上它們過於謹慎了,記錄被**定義爲元組,其中第一個元素是記錄名,然後按照與記錄定義中相同的順序跟隨記錄字段。然而,混合記錄語法和元組語法被認爲是糟糕的風格,因爲它消除了使用記錄的一個主要優點。 – rvirding

4

我認爲記錄可以直接用於模式匹配(這會比使用元組結構更好)。

defmodule Ween do 
    defrecord TimeSpot, at: nil, tag: nil 

    def proper?(TimeSpot[tag: "home"] = v), do: { true, "succeeded with: #{inspect v}"  } 
    def proper?(other),      do: { false, "failed with:  #{inspect other}" } 

    def sample, do: TimeSpot.new(tag: "home") 
end 
1

只是爲了完整性(因爲這個問題還是非常高的藥劑標籤的問題列表):作爲藥劑0.13,記錄被棄用(比使用Erlang代碼交互等)和現在的問題是最好的實現使用Structs。這也方便給你,你的願望多態性(結構是地圖的一種形式)

http://elixir-lang.org/getting_started/15.html 
+0

這些地圖與Erlang R17中引入的地圖是相同還是不同? –

+0

類別。有效的思路似乎是記錄鼓勵在OO風格中添加記錄中的功能(類似於你所做的),而「elixir/erlang方式」則鼓勵功能性方法。 因此,「Dict」作爲協議引入。然後,「地圖」是使用E17地圖類型的Dict協議的實現。然而,這個實現被聲明爲「對於少量值快速,但是對於較大量很慢」,因此也存在「HashDict」類型,其應該用於大量的鍵... –

+1

然而,Struct是種一個Map的最小實現,它不提供Dict協議功能,即對於所有實際的影響,它都是一個基本的散列類型。這似乎是「班級類型」的骨幹所需要的(不是正確的話,但希望你明白我的意思)。最新的演變(Elixir 0.14我認爲)是我們可以實現你可以包含的實現。結果就是你可以從你的基本「Struct」開始,並且包含Enumerable位,如果你想要這個功能......很酷 –