Qqwy

Qqwy

TypeCheck Core Team

Updating structs: Map.put vs %Foo{oldfoo | new: value} vs put_in

Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum.

In the (beta version of the) book, they update structs using Map.put/3. I’ve found myself doing the same in my own code. @hubertlepicki astutely observed that this opens up the opportunity for mistyped field names when updating your structs: This is totally allowed, the result of Map.put/3 will then be a map (instead of an instance of your struct).

Example:

iex> defmodule Foo do
iex>   defstruct bar: 1 , baz: 2
iex> end

iex> foo = %Foo{}
iex> foo |> Map.put(:qux, 4)
%{__struct__: Foo, bar: 1, baz: 2, qux: 4}  # <- note that it is printed as a map.

The other two methods known to me to update structs are:

  1. The special struct update syntax, %Foo{oldfoo | bar: 4}. This will result in a compile-time error when wrong field names are used. Drawback: It cannot be piped.
  2. put_in/2: newfoo = put_in(foo.bar, 4). This will also result in a compile-time error when a wrong field name is used. Drawback: It, too, cannot be piped.

put_in/3 (as in: newfoo = put_in(foo, [:bar], 4) would be able to be piped, but it is not available for structs; it only works on things that implement the Access protocol.

So what is the best way to update structs in practice? Am I missing any method in this list? Would it be a good idea to have a version of put_in that works on structs and is pipeable?

Most Liked

hubertlepicki

hubertlepicki

My eyes hurt. I do the same, but I die a bit every time I have to write it.

14
Post #4
NobbZ

NobbZ

The special Form %name{} pipes pretty well I think, you need to wrap in an anonymous funtion though):

iex(1)> defmodule S do
...(1)>   defstruct f: 0
...(1)> end
{:module, S, <<...>>, %S{f: 0}}
iex(2)> s = %S{}
%S{f: 0}
iex(3)> 1 |> (&%S{s | f: &1}).()
%S{f: 1}
iex(4)> s |> (&%S{&1 | f: &1.f + 5}).()
%S{f: 5}
11
Post #2
josevalim

josevalim

Creator of Elixir

@michalmuskala I always thought about put_existing and put_existing! (which neatly mirrors put_new).

Where Next?

Popular in Questions Top

aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I fore...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Other popular topics Top

Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39247 209
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
nobody
Hi! In PHP: $SERVER['SERVERADDR'] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35953 110
New
boundedvariable
I am going through the kafka architecture. All the features what the kafka is providing are already in Erlang. I would like hear your opi...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New

We're in Beta

About us Mission Statement