2013-12-22 65 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位,如果你想要这个功能......很酷 –