JSV.Helpers.Traverse (jsv v0.10.0)
View SourceHelpers to work with nested generic data structures.
Summary
Functions
Updates a data structure in depth-first, post-order traversal.
Updates a JSON-compatible data structure in depth-first, post-order traversal while carrying an accumulator.
Updates a data structure in depth-first, pre-order traversal.
Updates a JSON-compatible data structure in depth-first, pre-order traversal while carrying an accumulator.
Types
Functions
@spec postwalk(data, (postwalk_item() -> data)) :: data when data: term()
Updates a data structure in depth-first, post-order traversal.
Operates like postwalk/3
but without an accumulator. Handling continuations
for structs require to handle the accumulator, whose value MUST be nil
.
@spec postwalk(data, acc, (postwalk_item(), acc -> {data, acc})) :: {data, acc} when data: term(), acc: term()
Updates a JSON-compatible data structure in depth-first, post-order traversal while carrying an accumulator.
The callback must return a {new_value, new_acc}
tuple.
Nested data structures are given to the callback before their wrappers, and when the wrappers are called, their children are already updated.
JSON-compatible only means that there are restrictions on map keys and struct values:
The callback function will be called for any key but will not traverse the keys. For instance, with data such as
%{{x, y} => "some city"}
, the tuple used as key will be passed as-is but the callback will not be called for individual tuple elements.Structs will be passed as
{:struct, value, continuation}
. The struct keys and values will NOT have been traversed yet. To operate on the struct keys you MUST call it manually. To respect the post-order of traversal, it SHOULD be called before further transformation of the struct:Traverse.postwalk(%MyStruct, [], fn {:struct, my_struct, cont}, acc -> {map, acc} = cont.(Map.from_struct(my_struct), acc) {struct!(MyStruct, do_something_with_map(map)), acc} {:val, ...} -> ... end)
The continuation only accepts raw maps.
General data is accepted: tuples, pid, refs, etc. *
@spec prewalk(data, (prewalk_item() -> data)) :: data when data: term()
Updates a data structure in depth-first, pre-order traversal.
Operates like prewalk/3
but without an accumulator.
@spec prewalk(data, acc, (prewalk_item(), acc -> {data, acc})) :: {data, acc} when data: term(), acc: term()
Updates a JSON-compatible data structure in depth-first, pre-order traversal while carrying an accumulator.
The callback must return a {new_value, new_acc}
tuple.
Nested data structures are given iterated after the parent data has been given to the function. So it is possible to accept a container (map, list, tuple) and return another one from the callback before the children are iterated.
JSON-compatible only means that there are restrictions on map keys and struct values:
- The callback function will be called for any key but will not traverse the
keys. For instance, with data such as
%{{x, y} => "some city"}
, the tuple used as key will be passed as-is but the callback will not be called for individual tuple elements. - Structs are passed as a
{:struct, struct}
tuple. - General data is accepted: tuples, pid, refs, etc. *