# %Struct{} vs %{\_\_struct\_\_: Struct}

**URL:** <https://forum.elixirforum.com/t/struct-vs-struct-struct/36061>\
**Category:** Questions\
**Tags:** struct\
**Created:** [December 7, 2020, 11:28pm UTC](https://forum.elixirforum.com/t/struct-vs-struct-struct/36061 "2020-12-07T23:28:58Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![otuv](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/otuv/32/10976_2.png) [@otuv](https://forum.elixirforum.com/u/otuv)\
**Post date:** [December 7, 2020, 11:28pm UTC](https://forum.elixirforum.com/t/struct-vs-struct-struct/36061/1 "2020-12-07T23:28:58Z")

</div>

Hi,

Lets say I have a struct, lets say named **Struct** with the singular field x (default 0).

When I create it I get & **Struct** {x: 0}  
Since they are maps I then use Map.put to add something else like y: 5 I get %{ **struct** : S, x: 0, y: 5} and it is no longer an **Stuct**

Is there some way to purge any non struct fields and restore it to an **Struct**?

(Here the whole idea is obviously stupid)

---

<div class="post-metadata">

**Author:** ![gregvaughn](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/gregvaughn/32/954_2.png) [@gregvaughn](https://forum.elixirforum.com/u/gregvaughn)\
**Post date:** [December 8, 2020, 12:11am UTC](https://forum.elixirforum.com/t/struct-vs-struct-struct/36061/2 "2020-12-08T00:11:26Z")

</div>

Here’s one approach. I chose the URI struct because it’s small and in the std lib.

```elixir
iex(39)> u = URI.parse "http://forum.elixirforum.com"
%URI{
  authority: "forum.elixirforum.com",
  fragment: nil,
  host: "forum.elixirforum.com",
  path: nil,
  port: 80,
  query: nil,
  scheme: "http",
  userinfo: nil
}
iex(40)> m = Map.put(u, :y, 5)
%{
  __struct__ : URI,
  authority: "forum.elixirforum.com",
  fragment: nil,
  host: "forum.elixirforum.com",
  path: nil,
  port: 80,
  query: nil,
  scheme: "http",
  userinfo: nil,
  y: 5
}
iex(41)> s = struct(m. __struct__ , Map.from_struct(m))
%URI{
  authority: "forum.elixirforum.com",
  fragment: nil,
  host: "forum.elixirforum.com",
  path: nil,
  port: 80,
  query: nil,
  scheme: "http",
  userinfo: nil
}

```

`struct/2` ignores keys that are not specified in the struct itself

---

<div class="post-metadata">

**Author:** ![brettbeatty](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/brettbeatty/32/36494_2.png) [@brettbeatty](https://forum.elixirforum.com/u/brettbeatty)\
**Post date:** [December 8, 2020, 2:27am UTC](https://forum.elixirforum.com/t/struct-vs-struct-struct/36061/3 "2020-12-08T02:27:48Z")

</div>

I prefer the previous answer, but another option would get a list of keys expected in the struct and take them from the map.

Building on the other example:

```elixir
iex> Map.take(m, Map.keys(%URI{}))
%URI{
  authority: "forum.elixirforum.com",
  fragment: nil,
  host: "forum.elixirforum.com",
  path: nil,
  port: 80,
  query: nil,
  scheme: "http",
  userinfo: nil
}

```

Two downsides to this approach compared to the previous:

1. This solution won’t replace any missing keys.
2. This approach doesn’t let you create the struct dynamically (not without wrapping it in `struct/0` at least, which at that point you might as well do the other).

---

<div class="post-metadata">

**Author:** ![otuv](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/otuv/32/10976_2.png) [@otuv](https://forum.elixirforum.com/u/otuv)\
**Post date:** [December 8, 2020, 9:35pm UTC](https://forum.elixirforum.com/t/struct-vs-struct-struct/36061/4 "2020-12-08T21:35:51Z")

</div>

Looking at these answers I realized that my existing code is a bit backwards and what I really wanted can be done better with this solution.

Thank you both for replies!

---

<div class="post-metadata">

**Author:** ![ityonemo](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/ityonemo/32/11341_2.png) [@ityonemo](https://forum.elixirforum.com/u/ityonemo)\
**Post date:** [December 9, 2020, 12:49am UTC](https://forum.elixirforum.com/t/struct-vs-struct-struct/36061/5 "2020-12-09T00:49:22Z")

</div>

you can also use map cons, if you would like for your code to crash when you try to assign a nonexistent field, lets you catch errors in tests (how good is your test coverage? lol)

```elixir
defmodule S do
  defstruct [x: 0]
  def do_something(val = %S{}) do
     %{val | y: "oops"}
  end
end

```

will crash on do\_something. Whenever it’s a struct, I prefer using map cons for that bailout behaviour.
