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

Erlang(Elixir)中作为元组的记录模式匹配,erlang,pattern-matching,tuples,record,elixir,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:

在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 这里测试的元组模式匹配的原因是为了模拟记录的“某种”duck类型;我希望得到的最终结果应该是这样的:

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

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

Cesarini和Thompson在他们的书Erlang编程中说,永远不要依赖记录作为元组实现的事实,因为这种实现可能会改变。请参阅的公认答案。

我认为该记录可以直接用于模式匹配(这比使用元组结构要好)

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


另一个原因是您可能需要更改记录定义(例如添加新字段),在这种情况下,需要在Parroty解决方案仍然有效的情况下修改直接模式匹配。这是使用记录而不是元组的原因,因此不使用记录的直接模式匹配非常重要。事实上,由于过于谨慎,记录被定义为元组,其中第一个元素是记录名称,然后按照记录定义中的相同顺序跟随记录字段。但是,混合使用记录语法和元组语法被认为是一种不好的风格,因为它消除了使用记录的一个主要好处。这些映射与Erlang R17中引入的映射相同,或者是不同的。实际上,思维链似乎是记录鼓励以OO风格在记录中添加函数(类似于您所做的),而“elixir/erlang方式”是鼓励功能方法。因此,“Dict”作为协议被引入。然后,“映射”是使用E17映射类型的Dict协议的实现。然而,该实现被声明为“对于少量值快速,但是对于较大数量的值缓慢”,因此也有一种“HashDict”类型,可以用于大量密钥……然而,Struct是Map的一种最小实现,它不提供Dict协议功能,ie对于所有实际效果来说都是一种基本的散列类型。这似乎是“类类型”的主干所需要的(不是正确的词,但希望你明白我的意思)。最新的进展(Elixir0.14我认为)是我们可以有一些实现,您可以包括其中。结果是,您可以从您的基本“结构”开始,并包括可枚举位,如果您需要该功能。。。酷
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
http://elixir-lang.org/getting_started/15.html