I really wanted to avoid assigning the temporary map to a variable.
Well, because the data at a specific memory location is immutable, elixir can safely use pointers to those memory locations inside new collections. Therefore, creating a temporary variable with intermediate results does not double the amount of memory used. For instance, if you begin with a map that has 1 million entries and you create a new map with one additional entry, you do not use total memory of:
old_map new_map
| |
V V
1 million + ( 1 million + 1)
Rather you only use additional memory of:
new_entry
|
V
1 + pointer_to_old_map
...plus a little extra for the new map's bookkeeping. Like this:
old_map
^
|
new_map = %{ +, a: 10}
Is there a way to write immediately:
%{
total: 38,
value: 22,
ratio: __SELF__.value / __SELF__.total
}
Yes:
%{
total: 38,
value: 22,
ratio: 22/38
}
Now, if you have a list of maps to which you want to add a ratio key:
data = [
%{total: 38, value: 22},
%{total: 40, value: 22},
%{total: 44, value: 22}
]
for %{total: t, value: v}=map <- data do
Map.put(map, :ratio, v/t)
end
output:
[
%{ratio: 0.5789473684210527, total: 38, value: 22},
%{ratio: 0.55, total: 40, value: 22},
%{ratio: 0.5, total: 44, value: 22}
]
After each iteration of the for comprehension
, the memory locations of t
and v
are immediately subject to garbage collection and a pointer to the memory location of map
is used in the new map.