Elixir如何将Map结构转换为Record结构 [英] Elixir How to convert a Map struct to a Record struct

查看:172
本文介绍了Elixir如何将Map结构转换为Record结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a Record struct and a Map struct like:

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:

I can convert the Record to Map like this:

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

但是如何将地图转换为记录?

But how can I convert the Map to a Record?

推荐答案

不老长寿药记录已。 Elixir中现在存在的 Record 模块仅用于两件事:

Elixir Records are deprecated. The Record module that now exists in Elixir is only used for two things:


  1. 使用简短的内部数据

  2. 与Erlang记录进行交互

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

This means you should probably not be using them unless you are trying to extract record information from an Erlang file.

关于您的原始问题,这是我如何将Erlang Records和Elixir Structs转换回并向前。一旦您意识到一个结构只是一个 Map ,其中包含 __ struct__:Foo.Bar ,而一个Record ist只是以 {Foo.Bar,...} 开头的元组非常简单。唯一棘手的一点是,有关记录字段的信息仅在编译时可用。因此,默认情况下没有动态的方式来建立记录。据我所知,您只能通过将字段定义存储在某个地方并使用它来生成结构和记录定义来解决此问题。后来,相同的源被重新使用以构建具有默认值(即记录)的有序元组。请记住,您确实不应该使用记录。因此,请注意:丑陋的黑客;-)

Regarding your original question, here's how I would convert Erlang Records and Elixir Structs back and forth. Once you realize that a struct is just a Map that contains __struct__: Foo.Bar, and that a Record ist just a tuple that starts with {Foo.Bar, ...} it's pretty straightforward. The only tricky bit is that the information about the record fields is only available at compile time. Therefore, there is no dynamic way of building a record by default. As far as I know, you can only work around this by storing the field definitions somewhere, and use it to generate the struct and record definition. Later, the same source is re-used to build an ordered tuple with default values (i.e. the record). Remember, you really shouldn't use records. So, be warned: ugly hacks ahead ;-)

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结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆