我有一个Record结构和一个Map结构,例如:

defmodule Foo.Bar do
  defstruct boo: nil, baz: nil
end

defmodule Foo do
  require Record
  Record.defrecord :bar, Foo.Bar, [boo: nil, baz: nil]
end

我可以像这样将Record转换为Map:
defp update_map({k, v}, map), do: Map.update!(map, k, fn(_) -> v end)
defp rd2map(rd) do
  Foo.bar(rd) |> Enum.reduce(%Foo.Bar{}, &update_map/2)
end

但是,如何将 map 转换为记录?

最佳答案

Elixir Records are deprecated。 Elixir中现在存在的Record模块仅用于两件事:

  • 用于处理简短的内部数据
  • 与Erlang记录交互

  • 这意味着除非您试图从Erlang文件中提取记录信息,否则您可能不应该使用它们。

    关于您的原始问题,这是我如何来回转换Erlang Records和Elixir Structs的方法。一旦意识到一个结构只是一个包含Map__struct__: Foo.Bar,并且一个Record ist只是一个以{Foo.Bar, ...}开头的元组,就非常简单了。唯一棘手的一点是,有关记录字段的信息仅在编译时可用。因此,默认情况下没有动态的方式来建立记录。据我所知,您只能通过将字段定义存储在某个地方并使用它来生成结构和记录定义来解决此问题。后来,相同的源被重新使用以构建具有默认值(即记录)的有序元组。请记住,您真的不应使用记录。因此,请注意:前面有丑陋的技巧;-)
    defmodule Foo.Bar do
      @fields [boo: nil, baz: nil]
      def fields, do: @fields
      defstruct @fields
    end
    
    defmodule Foo do
      require Record
      Record.defrecord :bar, Foo.Bar, Foo.Bar.fields
    end
    
    defmodule Foo.Utils do
      require Foo
    
      def record_to_struct(record) do
        [{:__struct__, Foo.Bar} | Foo.bar(record)] |> Enum.into(%{})
      end
    
      def struct_to_record(struct) do
        map = Map.from_struct(struct)
        for {key, default} <- Foo.Bar.fields, into: [Foo.Bar] do
          Dict.get(map, key, default)
        end |> List.to_tuple
      end
    end
    

    关于Elixir如何将Map结构转换为Record结构,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28891758/

    10-12 21:48