brenocastelo

brenocastelo

There's any difference between map.put/3 and the built in Map update %{map | "key" => "value"}?

Hello, guys!

I was doing some exercises from exercism.io and in some moment a needed to update a Map, I did and finished the exercise. After a while, I found the function Enum.frequencies/1 that could have helped me on the exercise. I decided open Elixir source code to see implementation of Enum.frequencies/1 that is this:

  @doc since: "1.10.0"
  @spec frequencies(t) :: map
  def frequencies(enumerable) do
    reduce(enumerable, %{}, fn key, acc ->
      case acc do
        %{^key => value} -> %{acc | key => value + 1}
        %{} -> Map.put(acc, key, 1)
      end
    end)
  end

Then, the question came to me: There’s any difference between map.put/3 and the built in Map update %{map | “key” => “value”}?

I write my version of Enum.frequencies/1 using Enum.reduce/3, and I replaced %{^key => value} -> %{acc | key => value + 1} by %{^x => value} -> Map.put(acc, x, value + 1) and did work.
I would like to know if there is any reason for Elixir source code to use this syntax %{acc | key => value + 1} on Enum.frequencies/1

Most Liked

tovarchristian21

tovarchristian21

Hey, nice to see you are checking source code for solving doubts. Yes there’s a difference, when you update a map using the | operator, that key has to exist already. That is the reason on the case, if the key already exists they just increase the counter by updating the map using the | operator, but if the key is not present yet, the added it using the Map.put/3 function.

eksperimental

eksperimental

This is the equivalent of doing Map.update(acc, key, 1, &(&1 + 1))

derek-zhou

derek-zhou

In erlang, Map#{key => Value} means update or insert, and Map#{key := Value} means update only. In elixir the shorthand for upsert is removed to reduce confusion. So this is also a good example to showcase the difference two languages’ philosophy: Erlang favors logic and completeness, Elixir favors ergonomics and sane default.

al2o3cr

al2o3cr

FWIW, apparently (in 2019) the overhead of calling an anonymous function &(&1 + 1) was enough to inline Map.update in Enum.frequencies:

tovarchristian21

tovarchristian21

Yes, Map.put/3 can also update the value of an existent key. I would say that the right comparison here is with Map.update!/3 because using the shorthand update will lead to an update like this function does. So the thing that matters is if the key is present or not, you might want to know when trying to update a map if a certain key is present, because if it does not it can lead into an exception raise which you might be expecting, and using Map.put/3 will simply ignore that condition and set the key to the wanted value.

Where Next?

Popular in Questions Top

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
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
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
Phillipp
Hey, I have a NanoPi-M3 and try to install Elixir on their Ubuntu image. I followed the Raspberry Pi installation instructions from the ...
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
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
Exadra37
Sometimes I want to check if the input into a function is not a blank string. My first approach: defmodule Example do def do_stuff(s...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
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
jc00ke
Expanding on this topic: https://forum.elixirforum.net/t/map-typespec-question/19217 Let’s say I have a map with required and optional k...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs & Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3268 119930 1237
New
JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
peerreynders
Manning 2016 Halloween weekend sale via Deal of the Day Friday, October 28 - Half off all MEAPs - code WM102816LT Saturday, October 29 ...
326 29600 154
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
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
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
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
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

We're in Beta

About us Mission Statement