Erlang(Elixir)中作为元组记录的模式匹配

时间:2013-12-22 18:51:24

标签: erlang pattern-matching tuples record 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

因此,每个带有“标记”字段的记录都会显示“home”值,这与第一个子句匹配。当然,那里似乎会有一些性能损失。

3 个答案:

答案 0 :(得分:4)

Cesarini和Thompson在他们的书 Erlang Programming 中说,从不依赖于记录被实现为元组的事实,因为该实现可能会改变。请参阅this question的接受答案。

答案 1 :(得分: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

答案 2 :(得分:1)

只是为了完整性(因为这个问题在Elixir标记问题列表中仍然非常高):从Elixir 0.13开始,不推荐使用记录(除了与Erlang代码交互之外),现在使用Structs最好地实现了这个问题。这些也方便地为您提供了您想要的多态性(Structs是Map的一种形式)

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