The second argument of struct/2 must be of type Enum.t(). Let’s give it a whirl:
defmodule MyStruct do
defstruct [:a, :b]
end
defmodule B do
def go do
struct_struct = %MyStruct{a: 3, b: 4}
IO.inspect(struct_struct, label: "[struct_struct]")
map = %{"a" => 1, "b" => 2}
map_struct = Kernel.struct(MyStruct, map)
IO.inspect(map_struct, label: "[map_struct]")
end
end
map keys need to be atom key… as mentionned in the help
iex> h Kernel.struct
...
Keys in the Enumerable that don't exist in the struct are automatically
discarded. Note that keys must be atoms, as only atoms are allowed when
defining a struct.
You could do something like this…
fields = MyStruct.__schema__(:fields) |> Enum.map(& to_string(&1))
Enum.reduce(map, %MyStruct{}, fn {key, value}, acc ->
if to_string(key) in fields do
key = if is_binary(key), do: String.to_atom(key), else: key
%{acc | key => value}
else
acc
end
end)
seems to specify a map with either double quoted string keys or atom keys. I’ve never seen required() before in a type, and I’m not sure how the following would be different:
They’re the same, but one implicitly requires key/value pairs of those types and the other notation is explicit about the requiredness. There’s also optional(…) as the counterpart to required(…).