deep_merge v1.0.0 DeepMerge View Source
Provides functionality for deeply/recursively merging structures (normally for
Map
and Keyword
).
If you want to change the deep merge behavior of a custom struct,
please have a look at the DeepMerge.Resolver
protocol.
Link to this section Summary
Functions
The symbol to return in the function in deep_merge/3
when deep merging
should continue as normal
Deeply merges two maps or keyword list original
and override
A variant of DeepMerge.deep_merge/2
that allows to modify the merge behavior
through the additional passed in function
Link to this section Functions
continue_deep_merge()
View Source
continue_deep_merge() :: :__deep_merge_continue
continue_deep_merge() :: :__deep_merge_continue
The symbol to return in the function in deep_merge/3
when deep merging
should continue as normal.
Examples
iex> DeepMerge.continue_deep_merge
:__deep_merge_continue
deep_merge(original, override) View Source
Deeply merges two maps or keyword list original
and override
.
In more detail, if two conflicting values are maps or keyword lists themselves
then they will also be merged recursively. This is an extension in that sense
to what Map.merge/2
and Keyword.merge/2
do as it doesn't just override map
or keyword values but tries to merge them.
It does not merge structs or structs with maps. If you want your structs to be
merged then please have a look at the DeepMerge.Resolver
protocol and
consider implementing/deriving it.
Also, while it says Map
and Keyword
here, it is really dependent on which
types implement the DeepMerge.Resolver
protocol, which by default are Map
and Keyword
.
Examples
iex> DeepMerge.deep_merge(%{a: 1, b: [x: 10, y: 9]}, %{b: [y: 20, z: 30], c: 4})
%{a: 1, b: [x: 10, y: 20, z: 30], c: 4}
iex> DeepMerge.deep_merge(%{a: 1, b: %{x: 10, y: 9}}, %{b: %{y: 20, z: 30}, c: 4})
%{a: 1, b: %{x: 10, y: 20, z: 30}, c: 4}
iex> DeepMerge.deep_merge(%{a: 1, b: %{x: 10, y: 9}}, %{b: %{y: 20, z: 30}, c: 4})
%{a: 1, b: %{x: 10, y: 20, z: 30}, c: 4}
iex> DeepMerge.deep_merge([a: 1, b: [x: 10, y: 9]], [b: [y: 20, z: 30], c: 4])
[a: 1, b: [x: 10, y: 20, z: 30], c: 4]
iex> DeepMerge.deep_merge(%{a: 1, b: 2}, %{b: 3, c: 4})
%{a: 1, b: 3, c: 4}
iex> DeepMerge.deep_merge(%{a: 1, b: %{x: 10, y: 9}}, %{b: 5, c: 4})
%{a: 1, b: 5, c: 4}
iex> DeepMerge.deep_merge([a: [b: [c: 1, d: 2], e: [24]]], [a: [b: [f: 3], e: [42, 100]]])
[a: [b: [c: 1, d: 2, f: 3], e: [42, 100]]]
iex> DeepMerge.deep_merge(%{a: 1, b: 5}, %{b: %{x: 10, y: 9}, c: 4})
%{a: 1, b: %{x: 10, y: 9}, c: 4}
iex> DeepMerge.deep_merge(%{a: [b: %{c: [d: "foo", e: 2]}]}, %{a: [b: %{c: [d: "bar"]}]})
%{a: [b: %{c: [e: 2, d: "bar"]}]}
deep_merge(original, override, resolve_function) View Source
A variant of DeepMerge.deep_merge/2
that allows to modify the merge behavior
through the additional passed in function.
This is similar to the relationship between Map.merge/2
and Map.merge/3
and the structure of the function is exactly the same, e.g. the passed in
arguments are key
, original
and override
.
The function is called before a merge is performed. If it returns any value
that value is inserted at that point during the deep_merge. If the deep merge
should continue like normal you need to return the symbol returned by
DeepMerge.continue_deep_merge/0
.
If the merge conflict occurs at the top level then key
is nil
.
The example shows how this can be used to modify deep_merge
not to merge
keyword lists, in case you don't like that behavior.
Examples
iex> resolver = fn
...> (_, original, override) when is_list(original) and is_list(override) ->
...> override
...> (_, _original, _override) ->
...> DeepMerge.continue_deep_merge
...> end
iex> DeepMerge.deep_merge(%{a: %{b: 1}, c: [d: 1]},
...> %{a: %{z: 5}, c: [x: 0]}, resolver)
%{a: %{b: 1, z: 5}, c: [x: 0]}