Skip to content
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions lib/elixir/pages/getting-started/structs.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,28 @@ iex> %User{} = %{}

For more details on creating, updating, and pattern matching structs, see the documentation for `%/2`.

## Dynamic struct updates

When you need to update structs with data from variables or external sources, use `struct!/2`:

```elixir
iex> john = %User{name: "John", age: 27}
%User{age: 27, name: "John"}
iex> struct!(john, name: "Jane", age: 30)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this example is kind of wrong, you should probably use the map update syntax when you know exactly which fields are going to be updated, like in this case.

Suggested change
iex> struct!(john, name: "Jane", age: 30)
iex> %{john | name: "Jane", age: 30}

The second example seems more correct to me because the update comes from a variable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point. Also, data from external sources typically means string keys and may require casting, which isn't tackled by structs by default.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I agree with both points. Will update. I personally just discovered you can use struct/2 to update structs yesterday after like 5 years doing Elixir :D

%User{age: 30, name: "Jane"}
```

Unlike the update syntax, `struct!/2` accepts data from maps and keyword lists, and will raise an error if you try to set invalid fields:

```elixir
iex> fields = [name: "Jane", invalid: "field"]
[name: "Jane", invalid: "field"]
iex> struct!(john, fields)
** (KeyError) key :invalid not found in: %User{age: 27, name: "John"}
```

Always use `struct!/2` instead of `Map` functions when working with structs, as functions like `Map.put/3` and `Map.merge/2` can break struct integrity. See the [`Kernel.struct!/2`](https://hexdocs.pm/elixir/Kernel.html#struct!/2) documentation for more details.

## Structs are bare maps underneath

Structs are simply maps with a "special" field named `__struct__` that holds the name of the struct:
Expand Down