Elixir How to convert a structure structure to a record structure

I have a record structure and a structure structure, for example:

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 

I can convert the record to a card as follows:

 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 a card to a record?

+5
source share
2 answers

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

  • for working with short internal data
  • for interacting with Erlang records

This means that you probably shouldn't use them unless you are trying to extract information from an Erlang file.

As for your initial question, here's how I will 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 the record ist only a tuple starting with {Foo.Bar, ...} is pretty simple. The only tricky bit is that record field information is only available at compile time. Thus, by default there is no dynamic way to create a record. As far as I know, you can get around this only by storing field definitions somewhere and use it to generate a structure and record definition. Later, the same source is reused to create an ordered tuple with default values ​​(i.e. Records). Remember that you really should not use records. So be careful: ugly hacks are 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 
+10
source

All failures and Patrick's information are correct. You cannot solve the problem at runtime without annotating the fields.

However, you can solve this problem at compile time if you switch from an Erlang record (which is basically the only reason for using them). We do this on Elixir source code to convert Erlang #file_info{} to %File.Stat{} :

https://github.com/elixir-lang/elixir/blob/master/lib/elixir/lib/file/stat.ex

+2
source

Source: https://habr.com/ru/post/1214782/


All Articles