3

在 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”值的记录都将匹配第一个子句。当然,那里似乎会有一些性能损失。

4

3 回答 3

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
于 2013-12-22T23:53:23.633 回答
4

Cesarini 和 Thompson 在他们的《Erlang Programming 》一书中说,永远不要依赖记录作为元组实现的事实,因为这种实现可能会发生变化。请参阅此问题的已接受答案。

于 2013-12-22T18:58:53.687 回答
1

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

http://elixir-lang.org/getting_started/15.html
于 2014-07-07T19:00:15.467 回答