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

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.

WolfDan

WolfDan

Imo this is a elixir way as well to do it:

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

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

personally I’d prefer to create more functions like MrDoops pointed out, you can do anonymous functions as well

MrDoops

MrDoops

You can use Map.has_key?(data, :body) with a case statement. A more Elixir way might be to pattern match on the presence or absence of the map.

def process(%{body: _} = data), do: data
def process(%{} = data), do: %{data | body: nil}

Where Next?

Popular in Questions Top

albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
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
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
makeitrein
Hey all, just started picking up Elixir last week and am writing a scraper as a learning project. Baby step #1 is extracting the number ...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
mathew4509
I have a list say x = ["23gh", "56kh", "97mh"] I would like to pass each element to Val in each iteration. Say, in iteration 1 -------...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
wernerlaude
In AR this is so simple @articles = current_user.articles How to do in Ecto? def index(conn, _params) do current_user = conn.assig...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New

Other popular topics Top

vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
AstonJ
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

We're in Beta

About us Mission Statement