9mm

9mm

Elixir way to conditionally update a map

I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a loss how to do this without an if statement. I also don’t know if rebinding the same variable is a ‘code smell’

data = %{
  requireInteraction: true,
  title: title,
  icon: icon,
  click_action: click_action
}

if body do
  data = Map.put(data, :body, body)
end

First Post!

9mm

9mm

It also warns me of this. So confusing :s

Note variables defined inside case, cond, fn, if and similar do not leak. If you want to conditionally override an existing variable “data”, you will have to explicitly return the variable. For example:

Most Liked

gregvaughn

gregvaughn

I’ve written a helper function for this sort of thing before

def maybe_put(map, _key, nil), do: map
def maybe_put(map, key, value), do: Map.put(map, key, value)

Then you can use for multiple fields and pipe easily, for example:

data = %{
  requireInteraction: true,
  title: title,
  icon: icon,
  click_action: click_action
}
|> maybe_put(:body, body)
|> maybe_put(:other_field, other_value)
Eiji

Eiji

I don’t like to have two variables with same name in scope. For me such code is less readable.

If you have only one variable like that then use if or && with || instead like:

data = %{…}
updated_data = if body, do: Map.put(data, :body, body), else: data
# or
updated_data = body && Map.put(data, :body, body) || data

In case you need to do it multiple times then I recommend to do something like:

data = %{…}
data2 = %{example: 5, body: body, sample: 10}
Enum.reduce(data2, data, fn {key, value}, acc -> value && Map.put(acc, key, value) || acc)

This is equivalent for maps:

:maps.filter(fn _key, value -> not is_nil(value) end, data)
peerreynders

peerreynders

Statement mindset:

Expression mindset:

Statements don’t work in an expression based language - that’s why.

Last Post!

nwjlyons

nwjlyons

Map.merge/2 is another solution:

Map.merge(
  %{
    requireInteraction: true,
    title: title,
    icon: icon,
    click_action: click_action
  },
  if(body, do: %{body: body}, else: %{})
)

Where Next?

Popular in Questions Top

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
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
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
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
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 records...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 44265 214
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

We're in Beta

About us Mission Statement