JSV.Helpers.Traverse (jsv v0.5.0)
View SourceHelper module to read and write to generic Elixir 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.
Types
Functions
@spec postwalk(data, (traverse_callback_elem() -> data)) :: data when data: term()
Updates a data structure in depth-first, post-order traversal.
Operates like postwak/3
but without an accumulator. Handling continuations
for structs require to handle the accumulator, whose value MUST be nil
.
@spec postwalk(data, acc, (traverse_callback_elem(), 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 given called as-is but the callback will not be called for individual tuple elements.Structs will be passed as
{:struct, value, continuation}
. The truct 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. *