View Source ExRoseTree.Zipper (ExRoseTree v0.1.3)

A context-aware zipper for advanced traversal and manipulation of an ExRoseTree.

Accompanying the Zipper are a large number of both navigation primitives and more complex traversal functions built out of said primitives. An attempt has been made at providing semantically meaningful names for these primitives, drawing from gender-neutral, familial taxonomy (with a few liberties taken in creating neolisms to better suit the domain here), with the aim of establishing a sort of navigational pattern language.

The words first, last, next, and previous are ubiquitous and commonly paired with the likes of child, sibling, pibling (non-binary form of aunt/uncle), nibling (non-binary form of niece/nephew), and cousin to label specific navigation primitives. Other, less common words used for more specialized navigations include ancestral, descendant, and extended.

Care has been taken to make naming conventions reflect the expected operations as closely as possible, though there are a few cases where it might not be entirely obvious, particularly for some of the more specialized operations, so be sure to read the documentation closely and test for your use case when using a navigational function for the first time.

Many of these functions take an optional predicate() function which can be used to perform a navigational function until said predicate is satisfied. For example, ExRoseTree.Zipper.first_sibling(zipper, &(&1.term == 5)) will search, starting from the 0-th (first) index, the list of siblings that occur before but not after the current context for the first occurrence of a sibling with a term value equal to 5. If none are found, the context will not have been moved, and the function returns nil. Note, the predicate function will default to Util.always/1, which always returns true. When using the default predicate (in essence, not using a predicate) with this example, ExRoseTree.Zipper.first_sibling(zipper), the function will simply move the context to the first sibling of the initial context. If the are no previous siblings, it will return nil.

In general, most of the navigation primitives take constant time, while mutation is done at the current position and is a local operation.

Link to this section Summary

Types

t()

The Zipper struct represents a contextual position within an ExRoseTree.

Basic Functionality

Returns the current focus of the Zipper.

Returns the depth (as zero-based index) of the current focus.

Returns an empty Zipper.

Returns the children of the Zipper's current focus.

Returns the term of the current focus of the Zipper.

Builds a new Zipper from a list of ExRoseTree.Zipper.Locations.

Returns the index (zero-based) of the current focus with respect to any potential siblings it may have.

Applies the given function to the current focus.

Applies the given function to the focused children of the current focus.

Applies the given function to the term of the current focus.

Applies the given function to path of ExRoseTree.Zipper.Locations from the current focus back to the root without moving the Zipper.

Returns a new Zipper with its focus on the given ExRoseTree. Optionally take a list of previous and next sibling trees when using the :prev and :next keyword options.

Builds a new ExRoseTree.Zipper.Location out of the current Zipper.

Removes the current focus and then moves the focus to one of three places

Returns whether or not the current Zipper is at the root of the tree. A Zipper is considered at the root when it has no ExRoseTree.Zipper.Locations in its path.

Sets the current focus of the Zipper to the given ExRoseTree.

Sets the focused children to the given list of rose trees.

Sets the term of the current focus of the Zipper.

Moves a Zipper back to the root and returns a 2-tuple containing first, a list containing the previous siblings to the original root and second, a list containing the original root followed by its next siblings.

Moves a Zipper back to the root and returns the current focus, the root ExRoseTree.

Common Traversal

Accumulates an additional value using the provided acc_fn() while traversing the Zipper using the provided move_fn(). Returns a tuple including the new Zipper context and the accumulated value.

Using the given move_fn(), searches for the first tree that satisfies the given predicate function.

Traverses the Zipper using the provided move_fn() and maps the term at each node using the provided map_fn(). Returns the new Zipper with mapped values.

Repeats a call to the given move_fn(), by the given number of reps.

Moves a direction in the Zipper, determined by the move_fn(), if and only if the provided predicate function returns true when applied to the next node. Otherwise, returns nil.

Continuously moves a direction in the Zipper, determined by the move_fn(), until the provided predicate function returns true when applied to the next node. Otherwise, returns nil.

Repeats the given move_fn() while the given predicate remains true. If no custom predicate is given, the move_fn() will repeat until it no longer can.

Path Traversal

Rewinds the Zipper and accumulates an additional value using the provided acc_fn(). Returns a tuple including the root Zipper and the accumulated value.

Searches for a predicate match by rewinding the path in the Zipper. If no match is found, returns nil.

Rewinds a Zipper along the path by the given number of reps.

Rewinds a Zipper along the path if the provided predicate function returns true when applied to the parent node. Otherwise, returns nil.

Rewinds the Zipper and maps the term at each node using the provided map_fn(). Returns the new Zipper at the root with mapped values.

Rewinds a Zipper back to the root.

Rewinds a Zipper continuously until the provided predicate function returns true when applied to the next parent node. Otherwise, returns nil.

Rewinds a Zipper while the given predicate remains true. If no custom predicate is given, parent/1 will repeat until it reaches the root.

Breadth-first Traversal

Traverses backward through the Zipper in a breadth-first manner.

Moves backward in the Zipper and accumulates an additional value using the provided acc_fn(). Returns a tuple including the new Zipper and the accumulated value.

Searches for a predicate match by moving backward in the Zipper. If no match is found, returns nil.

Repeats a call to backward/1 by the given number of reps.

Moves backward in the Zipper if the provided predicate function returns true when applied to the next node. Otherwise, returns nil.

Moves backward in the Zipper and maps the term at each node using the provided map_fn(). Returns the new Zipper with mapped values.

Moves backward through the Zipper until the root has been reached. If the root has previous siblings, will move the the first sibling of the root.

Moves backward in the Zipper continuously until the provided predicate function returns true when applied to the next node. Otherwise, returns nil.

Moves backward in the Zipper while the given predicate remains true. If no custom predicate is given, backward/1 will repeat until it no longer can.

Traverses forward through the Zipper in a breadth-first manner.

Moves forward in the Zipper and accumulates an additional value using the provided acc_fn(). Returns a tuple including the new Zipper and the accumulated value.

Searches for a predicate match by moving forward in the Zipper. If no match is found, returns nil.

Repeats a call to forward/1 by the given number of reps.

Moves forward in the Zipper if the provided predicate function returns true when applied to the next node. Otherwise, returns nil.

Moves forward in the Zipper and maps the term at each node using the provided map_fn(). Returns the new Zipper with mapped values.

Moves forward through the Zipper until the last node of the tree has been reached.

Moves forward in the Zipper continuously until the provided predicate function returns true when applied to the next node. Otherwise, returns nil.

Moves forward in the Zipper while the given predicate remains true. If no custom predicate is given, forward/1 will repeat until it no longer can.

Depth-first Traversal

Traverses back through the Zipper in a depth-first manner.

Ascends the Zipper and accumulates an additional value using the provided acc_fn(). Returns a tuple including the new Zipper and the accumulated value.

Searches for a predicate match by ascending the Zipper. If no match is found, returns nil.

Repeats a call to ascend/1 by the given number of reps.

Ascends the Zipper if the provided predicate function returns true when applied to the next focus. Otherwise, returns nil.

Ascends the Zipper and maps the term at each node using the provided map_fn(). Returns the new Zipper with mapped values.

Ascends the Zipper until the root has been reached. If the root has previous siblings, will move the the first sibling of the root.

Ascends the Zipper continuously until the provided predicate function returns true when applied to the next focus. Otherwise, returns nil.

Ascends the Zipper while the given predicate remains true. If no custom predicate is given, ascend/1 will repeat until it no longer can.

Traverses forward through the Zipper in a depth-first manner.

Descends the Zipper and accumulates an additional value using the provided acc_fn(). Returns a tuple including the new Zipper and the accumulated value.

Searches for a predicate match by descending the Zipper. If no match is found, returns nil.

Repeats a call to descend/1 by the given number of reps.

Descends into the Zipper if the provided predicate function returns true when applied to the next focus. Otherwise, returns nil.

Descends the Zipper and maps the term at each node using the provided map_fn(). Returns the new Zipper with mapped values.

Descends the Zipper until the last node of the tree has been reached.

Descends into the Zipper continuously until the provided predicate function returns true when applied to the next focus. Otherwise, returns nil.

Descends the Zipper while the given predicate remains true. If no custom predicate is given, descend/1 will repeat until it no longer can.

Direct Ancestors

Moves the focus to the grandparent -- the parent of the parent -- of the focus, if possible. If there is no grandparent, returns nil.

Moves the focus to the great-grandparent -- parent of the grand-parent -- of the focus, if available. If there is no great-grandparent, returns nil.

Returns the index (zero-based) of the current focus' grandparent with respect to any potentital siblings it may have. If the current focus has no grandparent, returns nil.

Returns the index (zero-based) of the current focus' parent with respect to any potentital siblings it may have. If the current focus has no parent, returns nil.

Moves the focus to the parent ExRoseTree.Zipper.Location. If at the root, thus no parent, returns nil.

Returns the current Zipper's parent ExRoseTree.Zipper.Location.

Returns the term in the current Zipper's parent ExRoseTree.Zipper.Location.

Direct Descendants

Moves focus to the child at the specified index. If there are no children, or if the child does not exist at the index, returns nil.

Moves focus to the first child. If there are no children, and this is a leaf, returns nil.

Moves the focus to the first grandchild -- the first child of the first child -- of the focus. If there are no grandchildren, moves to the next sibling of the first child and looks for that tree's first child. This repeats until the first grandchild is found or it returns nil if none are found.

Moves the focus to the first great-grandchild -- the first child of the first grandchild -- of the focus. If there are no great-grandchildren, moves to the next sibling of the first grandchild and looks for that tree's first child. This repeats until the first great-grandchild is found or it returns nil if none are found.

Moves focus to the last child. If there are no children, and this is a leaf, returns nil.

Moves the focus to the last grandchild -- the last child of the last child -- of the focus. If there are no grandchildren, moves to the previous sibling of the last child and looks for that tree's last child. This repeats until the first grandchild is found or it returns nil if none are found.

Moves the focus to the last great-grandchild -- the last child of the last grandchild -- of the focus. If there are no great-grandchildren, moves to the previous sibling of the last grandchild and looks for that tree's last child. This repeats until the last great-grandchild is found or it returns nil if none are found.

Descend the left-most edge until it can go no further or until the optional predicate matches. Does not include siblings of starting focus.

Descend the right-most edge until it can go no further or until the optional predicate matches. Does not include siblings of starting focus.

Siblings

Appends a new sibling to the Zipper's next siblings.

Appends a new sibling to the Zipper's prev siblings.

Moves focus to the first sibling from the current focus. If there are no more siblings before the current focus, returns nil.

Inserts a new sibling in the Zipper's next siblings at the given index.

Inserts a new sibling in the Zipper's prev siblings at the given index.

Moves focus to the last sibling from the current focus. If there are no more siblings after the current focus, returns nil.

Applies the given function to all next siblings of the current focus without moving the Zipper.

Applies the given function to all previous siblings of the current focus without moving the Zipper.

Moves focus to the next sibling of the current focus. If there are no more siblings after the current focus, returns nil.

Returns the siblings that come after the current focus.

Removes the first sibling from the Zipper.

Removes the last sibling from the Zipper.

Removes the next sibling from the Zipper.

Removes a sibling from the Zipper's next siblings at the given index.

Removes the previous sibling from the Zipper.

Removes a sibling from the Zipper's prev siblings at the given index.

Prepends a new sibling to the Ziper's prev siblings.

Prepends a new sibling to the Zipper's next siblings.

Moves focus to the previous sibling to the current focus. If there are no more siblings before the current focus, returns nil.

Returns the siblings that come before the current focus.

Moves focus to the sibling of the current focus at the given index. If no sibling is found at that index, or if the provided index is the index for the current focus, returns nil.

Niblings: Nieces & Nephews

Recursively searches the descendant branches of the first sibling for the first "descendant nibling" of the current focus. That is, if a first nibling is found, it will then look for the first child of that tree (the "descendant nibling"). It will repeat the search if one is found, and it will continue until no more are found, returning the last one visited.

Searches for the first child of the first extended cousin--aka, the first extended nibling--of the focused tree.

Moves the focus to the first nibling -- the first child of the first sibling with children -- before the current focus. If not found, returns nil.

Moves the focus to the first nibling for a specific sibling -- the first child of the sibling at the given index -- of the current focus. If not found, returns nil.

Recursively searches the descendant branches of the last sibling for the last "descendant nibling" of the current focus. That is, if a last nibling is found, it will then look for the last child of that tree (the "descendant nibling"). It will repeat the search if one is found, and it will continue until no more are found, returning the last one visited.

Searches for the last child of the last extended cousin--aka, the last extended nibling--of the focused tree.

Moves the focus to the last nibling -- the last child of the last sibling with children -- before the current focus. If not found, returns nil.

Moves the focus to the last nibling for a specific sibling -- the last child of the sibling at the given index -- of the current focus. If not found, returns nil.

Recursively searches the descendant branches of the next sibling for the next "descendant nibling" of the current focus. That is, if a next nibling is found, it will then look for the first child of that tree (the "descendant nibling"). It will repeat the search if one is found, and it will continue until no more are found, returning the last one visited.

Searches for the first child of the next extended cousin--aka, the next extended nibling--of the focused tree.

Moves the focus to the next grand-nibling -- the first grandchild of the next sibling -- of the current focus. If not found, returns nil.

Moves the focus to the next nibling -- the first child of the first next sibling with children -- before the current focus. If not found, returns nil.

Recursively searches the descendant branches of the previous sibling for the previous "descendant nibling" of the current focus. That is, if a previous nibling is found, it will then look for the last child of that tree (the "descendant nibling"). It will repeat the search if one is found, and it will continue until no more are found, returning the last one visited.

Searches for the last child of the previous extended cousin--aka, the previous extended nibling--of the focused tree.

Moves the focus to the previous grand-nibling -- the last grandchild of the previous sibling -- of the current focus. If not found, returns nil.

Moves the focus to the previous nibling -- the last child of the first previous sibling with children -- before the current focus. If not found, returns nil.

Piblings: Aunts & Uncles

Recursively searches the path for the first, first "ancestral" pibling. That is, if a first pibling is not found for the parent, it will search the grandparent. If one is not found for the grandparent, it will search the great-grandparent. And so on, until it reaches the root. If the root is reached and it does not have a first pibling, the function returns nil.

Searches for the first extended cousin of the parent--aka, the first extended pibling--of the focused tree.

Moves the focus to the first grandpibling -- the first sibling of the grandparent -- of the current focus. If not found, returns nil.

Moves the focus to the first pibling -- the first sibling of the parent -- of the current focus. If not found, returns nil.

Recursively searches the path for the first, last "ancestral" pibling. That is, if a last pibling is not found for the parent, it will search the grandparent. If one is not found for the grandparent, it will search the great-grandparent. And so on, until it reaches the root. If the root is reached and it does not have a last pibling, the function returns nil.

Searches for the last extended cousin of the parent--aka, the last extended pibling--of the focused tree.

Moves the focus to the last grandpibling -- the last sibling of the grandparent -- of the current focus. If not found, returns nil.

Moves the focus to the last pibling -- the last sibling of the parent -- of the current focus. If not found, returns nil.

Recursively searches the path for the first, next "ancestral" pibling. That is, if a next pibling is not found for the parent, it will search the grandparent. If one is not found for the grandparent, it will search the great-grandparent. And so on, until it reaches the root. If the root is reached and it does not have a next pibling, the function returns nil.

Searches for the next extended cousin of the parent--aka, the next extended pibling--of the focused tree.

Moves the focus to the next grandpibling -- the next sibling of the grandparent -- of the current focus. If not found, returns nil.

Moves the focus to the next pibling -- the next sibling of the parent -- of the current focus. If not found, returns nil.

Moves the focus to the pibling of the current focus at the given index. If no pibling is found at that index, returns nil.

Recursively searches the path for the first, previous "ancestral" pibling. That is, if a previous pibling is not found for the parent, it will search the grandparent. If one is not found for the grandparent, it will search the great-grandparent. And so on, until it reaches the root. If the root is reached and it does not have a previous pibling, the function returns nil.

Searches for the previous extended cousin of the parent--aka, the previous extended pibling--of the focused tree.

Moves the focus to the previous grandpibling -- the previous sibling of the grandparent -- of the current focus. If not found, returns nil.

Moves the focus to the previous pibling -- the previous sibling of the parent -- of the current focus. If not found, returns nil.

First Cousins

Moves the focus to the first first-cousin -- the first child of the first pibling with children -- of the current focus. If not found, returns nil.

Moves the focus to the last first-cousin -- the last child of the last pibling with children -- of the current focus. If not found, returns nil.

Moves the focus to the next first-cousin -- the first child of the next pibling with children -- of the current focus. If not found, returns nil.

Moves the focus to the previous first-cousin -- the last child of the previous pibling with children -- of the current focus. If not found, returns nil.

Second Cousins

Moves the focus to the first second-cousin -- the first grandchild of the first grandpibling with grandchildren -- of the current focus. If not found, returns nil.

Moves the focus to the last second-cousin -- the last grandchild of the last grandpibling with grandchildren -- of the current focus. If not found, returns nil.

Moves the focus to the next second-cousin -- the first grandchild of the next grandpibling with grandchildren -- of the current focus. If not found, returns nil.

Moves the focus to the previous second-cousin -- the last grandchild of the previous grandpibling with grandchildren -- of the current focus. If not found, returns nil.

Extended Cousins

Searches for the first extended cousin or the first first-cousin of the focused tree.

Searches for the last extended cousin or the last first-cousin of the focused tree.

Searches for the next extended cousin or the next first-cousin of the focused tree.

Searches for the previous extended cousin or the previous first-cousin of the focused tree.

Link to this section Types

@type acc_fn() :: (t(), term() -> term())
@type map_fn() :: (t() -> t())
@type move_fn() :: (t() -> t() | nil)
@type predicate() :: (t() -> boolean())
@type t() :: %ExRoseTree.Zipper{
  focus: ExRoseTree.t(),
  next: [ExRoseTree.t()],
  path: [ExRoseTree.Zipper.Location.t()],
  prev: [ExRoseTree.t()]
}

The Zipper struct represents a contextual position within an ExRoseTree.

It includes the following important pieces:

  • focus - the current focus or context within the ExRoseTree.Zipper. Its type is that of an ExRoseTree.
  • prev - all siblings occurring before the current focus. It's type is a list of ExRoseTrees and is maintained in reverse order, so that the immediately previous sibling to the focus is at the head of the list.
  • next - all siblings occurring after the current focus. It's type is a list of ExRoseTrees and is maintained in standard order.
  • path - all direct ancestors of the the current focus back to the root node. It's type is a list of ExRoseTree.Zipper.Locations and is maintained in standard order. If the path is an empty list, then the Zipper is focused at the root node.

Link to this section Guards

Link to this macro

at_root?(value)

View Source (macro)
Link to this macro

has_children?(value)

View Source (macro)
Link to this macro

has_siblings?(value)

View Source (macro)
Link to this macro

zipper?(value)

View Source (macro)

Link to this section Basic Functionality

@spec current_focus(t()) :: ExRoseTree.t()

Returns the current focus of the Zipper.

examples

Examples

iex> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree)
...> ExRoseTree.Zipper.current_focus(z)
%ExRoseTree{term: 5, children: []}
@spec depth_of_focus(t()) :: non_neg_integer()

Returns the depth (as zero-based index) of the current focus.

examples

Examples

iex> loc_trees = for n <- [4,3,2,1], do: ExRoseTree.new(n)
...> locs = for n <- loc_trees, do: ExRoseTree.Zipper.Location.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, path: locs)
...> ExRoseTree.Zipper.depth_of_focus(z)
4
@spec empty() :: t()

Returns an empty Zipper.

examples

Examples

iex> ExRoseTree.Zipper.empty()
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: nil, children: []},
  prev: [],
  next: [],
  path: []
}
Link to this function

focused_children(zipper)

View Source
@spec focused_children(t()) :: [ExRoseTree.t()]

Returns the children of the Zipper's current focus.

A shortcut to ExRoseTree.get_children/1.

examples

Examples

iex> tree = ExRoseTree.new(5, [1,2,3,4])
...> z = ExRoseTree.Zipper.new(tree)
...> ExRoseTree.Zipper.focused_children(z)
[
  %ExRoseTree{term: 1, children: []},
  %ExRoseTree{term: 2, children: []},
  %ExRoseTree{term: 3, children: []},
  %ExRoseTree{term: 4, children: []}
]
@spec focused_term(t()) :: term()

Returns the term of the current focus of the Zipper.

A shortcut to using ExRoseTree.get_term/1.

examples

Examples

iex> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree)
...> ExRoseTree.Zipper.focused_term(z)
5
@spec from_locations([ExRoseTree.Zipper.Location.t()]) :: t()

Builds a new Zipper from a list of ExRoseTree.Zipper.Locations.

examples

Examples

iex> locs = for loc <- [3,2,1], do: ExRoseTree.Zipper.Location.new(loc)
...> ExRoseTree.Zipper.from_locations(locs)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 3, children: []},
  prev: [],
  next: [],
  path: [
    %ExRoseTree.Zipper.Location{
      prev: [],
      term: 2,
      next: []
    },
    %ExRoseTree.Zipper.Location{
      prev: [],
      term: 1,
      next: []
    }
  ]
}
@spec index_of_focus(t()) :: non_neg_integer()

Returns the index (zero-based) of the current focus with respect to any potential siblings it may have.

examples

Examples

iex> prev = for n <- [1,2,3,4], do: ExRoseTree.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, prev: prev)
...> ExRoseTree.Zipper.index_of_focus(z)
4
Link to this function

map_focus(zipper, map_fn)

View Source
@spec map_focus(t(), (ExRoseTree.t() -> ExRoseTree.t())) :: t()

Applies the given function to the current focus.

examples

Examples

iex> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree)
...> map_fn = &ExRoseTree.set_children(&1, [6,7,8,9])
...> ExRoseTree.Zipper.map_focus(z, &map_fn.(&1))
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 5, children: [
    %ExRoseTree{term: 6, children: []},
    %ExRoseTree{term: 7, children: []},
    %ExRoseTree{term: 8, children: []},
    %ExRoseTree{term: 9, children: []},
  ]},
  prev: [],
  next: [],
  path: []
}
Link to this function

map_focused_children(zipper, map_fn)

View Source
@spec map_focused_children(t(), (ExRoseTree.t() -> ExRoseTree.t())) :: t()

Applies the given function to the focused children of the current focus.

A shortcut to ExRoseTree.map_children/2 and set_focus/2.

examples

Examples

iex> tree = ExRoseTree.new(5, [1,2,3,4])
...> z = ExRoseTree.Zipper.new(tree)
...> map_fn = &ExRoseTree.map_term(&1, fn x -> x * 2 end)
...> ExRoseTree.Zipper.map_focused_children(z, map_fn)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 5, children: [
    %ExRoseTree{term: 2, children: []},
    %ExRoseTree{term: 4, children: []},
    %ExRoseTree{term: 6, children: []},
    %ExRoseTree{term: 8, children: []}
  ]},
  prev: [],
  next: [],
  path: []
}
Link to this function

map_focused_term(zipper, map_fn)

View Source
@spec map_focused_term(t(), (term() -> term())) :: t()

Applies the given function to the term of the current focus.

A shortcut to using ExRoseTree.map_term/2 with set_focus/2.

examples

Examples

iex> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree)
...> map_fn = fn term -> term * 2 end
...> ExRoseTree.Zipper.map_focused_term(z, &map_fn.(&1))
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 10, children: []},
  prev: [],
  next: [],
  path: []
}
Link to this function

map_path(zipper, map_fn)

View Source
@spec map_path(
  t(),
  (ExRoseTree.Zipper.Location.t() -> ExRoseTree.Zipper.Location.t())
) :: t()

Applies the given function to path of ExRoseTree.Zipper.Locations from the current focus back to the root without moving the Zipper.

examples

Examples

iex> path = for n <- [4,3,2,1], do: ExRoseTree.Zipper.Location.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, path: path)
...> map_fn = &ExRoseTree.Zipper.Location.map_term(&1, fn term -> term * 2 end)
...> ExRoseTree.Zipper.map_path(z, &map_fn.(&1))
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 5, children: []},
  prev: [],
  next: [],
  path: [
    %ExRoseTree.Zipper.Location{prev: [], term: 8, next: []},
    %ExRoseTree.Zipper.Location{prev: [], term: 6, next: []},
    %ExRoseTree.Zipper.Location{prev: [], term: 4, next: []},
    %ExRoseTree.Zipper.Location{prev: [], term: 2, next: []}]
}
@spec new(
  ExRoseTree.t(),
  keyword()
) :: t()

Returns a new Zipper with its focus on the given ExRoseTree. Optionally take a list of previous and next sibling trees when using the :prev and :next keyword options.

Note that a Zipper maintains the list of previous siblings in reverse order internally, and this function performs that reversal itself, so do not pre-reverse your list of previous siblings when using that option!

examples

Examples

iex> tree = ExRoseTree.new(5)
...> ExRoseTree.Zipper.new(tree)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 5, children: []},
  prev: [],
  next: [],
  path: []
}

iex> prev = for n <- [1,2,3,4], do: ExRoseTree.new(n)
...> tree = ExRoseTree.new(5)
...> ExRoseTree.Zipper.new(tree, prev: prev)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 5, children: []},
  prev: [
    %ExRoseTree{term: 4, children: []},
    %ExRoseTree{term: 3, children: []},
    %ExRoseTree{term: 2, children: []},
    %ExRoseTree{term: 1, children: []}
  ],
  next: [],
  path: []
}

iex> loc_trees = for n <- [4,3,2,1], do: ExRoseTree.new(n)
...> locs = for n <- loc_trees, do: ExRoseTree.Zipper.Location.new(n)
...> tree = ExRoseTree.new(5)
...> ExRoseTree.Zipper.new(tree, path: locs)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 5, children: []},
  prev: [],
  next: [],
  path: [
    %ExRoseTree.Zipper.Location{prev: [], term: 4, next: []},
    %ExRoseTree.Zipper.Location{prev: [], term: 3, next: []},
    %ExRoseTree.Zipper.Location{prev: [], term: 2, next: []},
    %ExRoseTree.Zipper.Location{prev: [], term: 1, next: []}
  ]
}
@spec new_location(t()) :: ExRoseTree.Zipper.Location.t()

Builds a new ExRoseTree.Zipper.Location out of the current Zipper.

examples

Examples

iex> next = for n <- [6,7,8,9], do: ExRoseTree.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, next: next)
...> ExRoseTree.Zipper.new_location(z)
%ExRoseTree.Zipper.Location{
  prev: [],
  term: 5,
  next: [
    %ExRoseTree{term: 6, children: []},
    %ExRoseTree{term: 7, children: []},
    %ExRoseTree{term: 8, children: []},
    %ExRoseTree{term: 9, children: []}
  ]
}
@spec remove_focus(t()) :: {t(), ExRoseTree.t() | nil}

Removes the current focus and then moves the focus to one of three places:

  1. the next sibling, if one exists,
  2. else the previous sibling, if one exists,
  3. else the parent, if one exists

If none of those conditions exist, it will return an empty Zipper. In any case, the new Zipper will be returned as the first item in a tuple, while the removed focus will be returned as the second item.

examples

Examples

iex> tree = ExRoseTree.new(5)
...> prev_siblings = for n <- [3,4], do: ExRoseTree.new(n)
...> next_siblings = for n <- [6,7], do: ExRoseTree.new(n)
...> z = ExRoseTree.Zipper.new(tree, prev: prev_siblings, next: next_siblings)
...> ExRoseTree.Zipper.remove_focus(z)
{%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 6, children: []},
  prev: [
    %ExRoseTree{term: 4, children: []},
    %ExRoseTree{term: 3, children: []}
  ],
  next: [
    %ExRoseTree{term: 7, children: []}
  ],
  path: []
},
%ExRoseTree{term: 5, children: []}}
@spec root?(t()) :: boolean()

Returns whether or not the current Zipper is at the root of the tree. A Zipper is considered at the root when it has no ExRoseTree.Zipper.Locations in its path.

examples

Examples

iex> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree)
...> ExRoseTree.Zipper.root?(z)
true
Link to this function

set_focus(zipper, new_focus)

View Source
@spec set_focus(t(), ExRoseTree.t()) :: t()

Sets the current focus of the Zipper to the given ExRoseTree.

examples

Examples

iex> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.empty()
...> ExRoseTree.Zipper.set_focus(z, tree)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 5, children: []},
  prev: [],
  next: [],
  path: []
}
Link to this function

set_focused_children(zipper, new_children)

View Source
@spec set_focused_children(t(), [ExRoseTree.t()]) :: t()

Sets the focused children to the given list of rose trees.

A shortcut to ExRoseTree.set_children/2 and set_focus/2.

examples

Examples

iex> tree = ExRoseTree.new(5, [1,2,3,4])
...> z = ExRoseTree.Zipper.new(tree)
...> new_children = for t <- [6,7,8,9], do: ExRoseTree.new(t)
...> ExRoseTree.Zipper.set_focused_children(z, new_children)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 5, children: [
    %ExRoseTree{term: 6, children: []},
    %ExRoseTree{term: 7, children: []},
    %ExRoseTree{term: 8, children: []},
    %ExRoseTree{term: 9, children: []}
  ]},
  prev: [],
  next: [],
  path: []
}
Link to this function

set_focused_term(zipper, new_term)

View Source
@spec set_focused_term(t(), term()) :: t()

Sets the term of the current focus of the Zipper.

A shortcut to using ExRoseTree.set_term/2 with set_focus/2.

examples

Examples

iex> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree)
...> ExRoseTree.Zipper.set_focused_term(z, 10)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 10, children: []},
  prev: [],
  next: [],
  path: []
}
@spec to_forest(t()) :: {[ExRoseTree.t()], [ExRoseTree.t()]}

Moves a Zipper back to the root and returns a 2-tuple containing first, a list containing the previous siblings to the original root and second, a list containing the original root followed by its next siblings.

examples

Examples

iex> tree = ExRoseTree.new(3, [6])
...> prev_trees = for t <- [1,2], do: ExRoseTree.new(t)
...> next_trees = for t <- [4,5], do: ExRoseTree.new(t)
...> z = ExRoseTree.Zipper.new(tree, prev: prev_trees, next: next_trees)
...> z = Zipper.last_child(z)
...> Zipper.to_forest(z)
{
  [
    %ExRoseTree{term: 1, children: []},
    %ExRoseTree{term: 2, children: []}
  ],
  [
    %ExRoseTree{term: 3, children: [%ExRoseTree{term: 6, children: []}]},
    %ExRoseTree{term: 4, children: []},
    %ExRoseTree{term: 5, children: []}
  ]
}
@spec to_tree(t()) :: ExRoseTree.t()

Moves a Zipper back to the root and returns the current focus, the root ExRoseTree.

examples

Examples

iex> tree = ExRoseTree.new(5, [1,2,3,4])
...> z = ExRoseTree.Zipper.new(tree)
...> z = Zipper.last_child(z)
...> Zipper.to_tree(z)
%ExRoseTree{
  term: 5,
  children: [
    %ExRoseTree{term: 1, children: []},
    %ExRoseTree{term: 2, children: []},
    %ExRoseTree{term: 3, children: []},
    %ExRoseTree{term: 4, children: []},
  ]
}

Link to this section Common Traversal

Link to this function

accumulate(zipper, move_fn, acc, acc_fn)

View Source
@spec accumulate(t(), move_fn(), term(), acc_fn()) :: {t(), term()}

Accumulates an additional value using the provided acc_fn() while traversing the Zipper using the provided move_fn(). Returns a tuple including the new Zipper context and the accumulated value.

Link to this function

find(zipper, move_fn, predicate)

View Source
@spec find(t(), move_fn(), predicate()) :: t() | nil

Using the given move_fn(), searches for the first tree that satisfies the given predicate function.

Link to this function

map(zipper, move_fn, map_fn)

View Source
@spec map(t(), move_fn(), map_fn()) :: t()

Traverses the Zipper using the provided move_fn() and maps the term at each node using the provided map_fn(). Returns the new Zipper with mapped values.

Link to this function

move_for(zipper, move_fn, reps)

View Source
@spec move_for(
  t(),
  move_fn(),
  pos_integer()
) :: t() | nil

Repeats a call to the given move_fn(), by the given number of reps.

examples

Examples

iex> loc_trees = for n <- [4,3,2,1], do: ExRoseTree.new(n)
...> locs = for n <- loc_trees, do: ExRoseTree.Zipper.Location.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, path: locs)
...> move_fn = &ExRoseTree.Zipper.parent/1
...> z = ExRoseTree.Zipper.move_for(z, move_fn, 2)
...> ExRoseTree.Zipper.current_focus(z).term
3
Link to this function

move_if(zipper, move_fn, predicate)

View Source
@spec move_if(t(), move_fn(), predicate()) :: t() | nil

Moves a direction in the Zipper, determined by the move_fn(), if and only if the provided predicate function returns true when applied to the next node. Otherwise, returns nil.

Link to this function

move_until(zipper, move_fn, predicate)

View Source
@spec move_until(t(), move_fn(), predicate()) :: t() | nil

Continuously moves a direction in the Zipper, determined by the move_fn(), until the provided predicate function returns true when applied to the next node. Otherwise, returns nil.

Link to this function

move_while(zipper, move_fn, predicate \\ &Util.always/1)

View Source
@spec move_while(t(), move_fn(), predicate()) :: t()

Repeats the given move_fn() while the given predicate remains true. If no custom predicate is given, the move_fn() will repeat until it no longer can.

Link to this section Path Traversal

Link to this function

rewind_accumulate(zipper, acc, acc_fn)

View Source
@spec rewind_accumulate(t(), term(), acc_fn()) :: {t(), term()}

Rewinds the Zipper and accumulates an additional value using the provided acc_fn(). Returns a tuple including the root Zipper and the accumulated value.

Link to this function

rewind_find(zipper, predicate)

View Source
@spec rewind_find(t(), predicate()) :: t() | nil

Searches for a predicate match by rewinding the path in the Zipper. If no match is found, returns nil.

Link to this function

rewind_for(zipper, reps)

View Source
@spec rewind_for(t(), pos_integer()) :: t() | nil

Rewinds a Zipper along the path by the given number of reps.

Link to this function

rewind_if(zipper, predicate)

View Source
@spec rewind_if(t(), predicate()) :: t() | nil

Rewinds a Zipper along the path if the provided predicate function returns true when applied to the parent node. Otherwise, returns nil.

Link to this function

rewind_map(zipper, map_fn)

View Source
@spec rewind_map(t(), map_fn()) :: t()

Rewinds the Zipper and maps the term at each node using the provided map_fn(). Returns the new Zipper at the root with mapped values.

@spec rewind_to_root(t()) :: t()

Rewinds a Zipper back to the root.

examples

Examples

iex> loc_trees = for n <- [4,3,2,1], do: ExRoseTree.new(n)
...> locs = for n <- loc_trees, do: ExRoseTree.Zipper.Location.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, path: locs)
...> z = ExRoseTree.Zipper.rewind_to_root(z)
...> ExRoseTree.Zipper.root?(z)
true
Link to this function

rewind_until(zipper, predicate)

View Source
@spec rewind_until(t(), predicate()) :: t() | nil

Rewinds a Zipper continuously until the provided predicate function returns true when applied to the next parent node. Otherwise, returns nil.

Link to this function

rewind_while(zipper, predicate \\ &Util.always/1)

View Source
@spec rewind_while(t(), predicate()) :: t()

Rewinds a Zipper while the given predicate remains true. If no custom predicate is given, parent/1 will repeat until it reaches the root.

Link to this section Breadth-first Traversal

@spec backward(t()) :: t()

Traverses backward through the Zipper in a breadth-first manner.

Link to this function

backward_accumulate(zipper, acc, acc_fn)

View Source
@spec backward_accumulate(t(), term(), acc_fn()) :: {t(), term()}

Moves backward in the Zipper and accumulates an additional value using the provided acc_fn(). Returns a tuple including the new Zipper and the accumulated value.

Link to this function

backward_find(zipper, predicate)

View Source
@spec backward_find(t(), predicate()) :: t() | nil

Searches for a predicate match by moving backward in the Zipper. If no match is found, returns nil.

Link to this function

backward_for(zipper, reps)

View Source
@spec backward_for(t(), pos_integer()) :: t() | nil

Repeats a call to backward/1 by the given number of reps.

Link to this function

backward_if(zipper, predicate)

View Source
@spec backward_if(t(), predicate()) :: t() | nil

Moves backward in the Zipper if the provided predicate function returns true when applied to the next node. Otherwise, returns nil.

Link to this function

backward_map(zipper, map_fn)

View Source
@spec backward_map(t(), map_fn()) :: t()

Moves backward in the Zipper and maps the term at each node using the provided map_fn(). Returns the new Zipper with mapped values.

Link to this function

backward_to_root(zipper)

View Source
@spec backward_to_root(t()) :: t()

Moves backward through the Zipper until the root has been reached. If the root has previous siblings, will move the the first sibling of the root.

Link to this function

backward_until(zipper, predicate)

View Source
@spec backward_until(t(), predicate()) :: t() | nil

Moves backward in the Zipper continuously until the provided predicate function returns true when applied to the next node. Otherwise, returns nil.

Link to this function

backward_while(zipper, predicate \\ &Util.always/1)

View Source
@spec backward_while(t(), predicate()) :: t()

Moves backward in the Zipper while the given predicate remains true. If no custom predicate is given, backward/1 will repeat until it no longer can.

@spec forward(t()) :: t() | nil

Traverses forward through the Zipper in a breadth-first manner.

Link to this function

forward_accumulate(zipper, acc, acc_fn)

View Source
@spec forward_accumulate(t(), term(), acc_fn()) :: {t(), term()}

Moves forward in the Zipper and accumulates an additional value using the provided acc_fn(). Returns a tuple including the new Zipper and the accumulated value.

Link to this function

forward_find(zipper, predicate)

View Source
@spec forward_find(t(), predicate()) :: t() | nil

Searches for a predicate match by moving forward in the Zipper. If no match is found, returns nil.

Link to this function

forward_for(zipper, reps)

View Source
@spec forward_for(t(), pos_integer()) :: t() | nil

Repeats a call to forward/1 by the given number of reps.

Link to this function

forward_if(zipper, predicate)

View Source
@spec forward_if(t(), predicate()) :: t() | nil

Moves forward in the Zipper if the provided predicate function returns true when applied to the next node. Otherwise, returns nil.

Link to this function

forward_map(zipper, map_fn)

View Source
@spec forward_map(t(), map_fn()) :: t()

Moves forward in the Zipper and maps the term at each node using the provided map_fn(). Returns the new Zipper with mapped values.

@spec forward_to_last(t()) :: t()

Moves forward through the Zipper until the last node of the tree has been reached.

Link to this function

forward_until(zipper, predicate)

View Source
@spec forward_until(t(), predicate()) :: t() | nil

Moves forward in the Zipper continuously until the provided predicate function returns true when applied to the next node. Otherwise, returns nil.

Link to this function

forward_while(zipper, predicate \\ &Util.always/1)

View Source
@spec forward_while(t(), predicate()) :: t()

Moves forward in the Zipper while the given predicate remains true. If no custom predicate is given, forward/1 will repeat until it no longer can.

Link to this section Depth-first Traversal

@spec ascend(t()) :: t()

Traverses back through the Zipper in a depth-first manner.

Link to this function

ascend_accumulate(zipper, acc, acc_fn)

View Source
@spec ascend_accumulate(t(), term(), acc_fn()) :: {t(), term()}

Ascends the Zipper and accumulates an additional value using the provided acc_fn(). Returns a tuple including the new Zipper and the accumulated value.

Link to this function

ascend_find(zipper, predicate)

View Source
@spec ascend_find(t(), predicate()) :: t() | nil

Searches for a predicate match by ascending the Zipper. If no match is found, returns nil.

Link to this function

ascend_for(zipper, reps)

View Source
@spec ascend_for(t(), pos_integer()) :: t() | nil

Repeats a call to ascend/1 by the given number of reps.

Link to this function

ascend_if(zipper, predicate)

View Source
@spec ascend_if(t(), predicate()) :: t() | nil

Ascends the Zipper if the provided predicate function returns true when applied to the next focus. Otherwise, returns nil.

Link to this function

ascend_map(zipper, map_fn)

View Source
@spec ascend_map(t(), map_fn()) :: t()

Ascends the Zipper and maps the term at each node using the provided map_fn(). Returns the new Zipper with mapped values.

@spec ascend_to_root(t()) :: t()

Ascends the Zipper until the root has been reached. If the root has previous siblings, will move the the first sibling of the root.

Link to this function

ascend_until(zipper, predicate)

View Source
@spec ascend_until(t(), predicate()) :: t() | nil

Ascends the Zipper continuously until the provided predicate function returns true when applied to the next focus. Otherwise, returns nil.

Link to this function

ascend_while(zipper, predicate \\ &Util.always/1)

View Source
@spec ascend_while(t(), predicate()) :: t()

Ascends the Zipper while the given predicate remains true. If no custom predicate is given, ascend/1 will repeat until it no longer can.

@spec descend(t()) :: t() | nil

Traverses forward through the Zipper in a depth-first manner.

Link to this function

descend_accumulate(zipper, acc, acc_fn)

View Source
@spec descend_accumulate(t(), term(), acc_fn()) :: {t(), term()}

Descends the Zipper and accumulates an additional value using the provided acc_fn(). Returns a tuple including the new Zipper and the accumulated value.

Link to this function

descend_find(zipper, predicate)

View Source
@spec descend_find(t(), predicate()) :: t() | nil

Searches for a predicate match by descending the Zipper. If no match is found, returns nil.

Link to this function

descend_for(zipper, reps)

View Source
@spec descend_for(t(), pos_integer()) :: t() | nil

Repeats a call to descend/1 by the given number of reps.

Link to this function

descend_if(zipper, predicate)

View Source
@spec descend_if(t(), predicate()) :: t() | nil

Descends into the Zipper if the provided predicate function returns true when applied to the next focus. Otherwise, returns nil.

Link to this function

descend_map(zipper, map_fn)

View Source
@spec descend_map(t(), map_fn()) :: t()

Descends the Zipper and maps the term at each node using the provided map_fn(). Returns the new Zipper with mapped values.

@spec descend_to_last(t()) :: t()

Descends the Zipper until the last node of the tree has been reached.

Link to this function

descend_until(zipper, predicate)

View Source
@spec descend_until(t(), predicate()) :: t() | nil

Descends into the Zipper continuously until the provided predicate function returns true when applied to the next focus. Otherwise, returns nil.

Link to this function

descend_while(zipper, predicate \\ &Util.always/1)

View Source
@spec descend_while(t(), predicate()) :: t()

Descends the Zipper while the given predicate remains true. If no custom predicate is given, descend/1 will repeat until it no longer can.

Link to this section Direct Ancestors

@spec grandparent(t()) :: t() | nil

Moves the focus to the grandparent -- the parent of the parent -- of the focus, if possible. If there is no grandparent, returns nil.

Link to this function

great_grandparent(zipper)

View Source
@spec great_grandparent(t()) :: t() | nil

Moves the focus to the great-grandparent -- parent of the grand-parent -- of the focus, if available. If there is no great-grandparent, returns nil.

Link to this function

index_of_grandparent(zipper)

View Source
@spec index_of_grandparent(t()) :: non_neg_integer() | nil

Returns the index (zero-based) of the current focus' grandparent with respect to any potentital siblings it may have. If the current focus has no grandparent, returns nil.

examples

Examples

iex> grandparent_siblings = for n <- [3,2,1], do: ExRoseTree.new(n)
...> grandparent_loc = ExRoseTree.Zipper.Location.new(4, prev: grandparent_siblings)
...> parent_loc = ExRoseTree.Zipper.Location.new(5)
...> tree = ExRoseTree.new(6)
...> z = ExRoseTree.Zipper.new(tree, path: [parent_loc, grandparent_loc])
...> ExRoseTree.Zipper.index_of_grandparent(z)
3
@spec index_of_parent(t()) :: non_neg_integer() | nil

Returns the index (zero-based) of the current focus' parent with respect to any potentital siblings it may have. If the current focus has no parent, returns nil.

examples

Examples

iex> parent_siblings = for n <- [3,2,1], do: ExRoseTree.new(n)
...> parent_loc = ExRoseTree.Zipper.Location.new(4, prev: parent_siblings)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, path: [parent_loc])
...> ExRoseTree.Zipper.index_of_parent(z)
3
@spec parent(t()) :: t() | nil

Moves the focus to the parent ExRoseTree.Zipper.Location. If at the root, thus no parent, returns nil.

examples

Examples

iex> prev = for n <- [3,4], do: ExRoseTree.new(n)
...> loc_trees = for n <- [2,1], do: ExRoseTree.new(n)
...> locs = for n <- loc_trees, do: ExRoseTree.Zipper.Location.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, prev: prev, path: locs)
...> ExRoseTree.Zipper.parent(z)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{
    term: 2,
    children: [
      %ExRoseTree{term: 3, children: []},
      %ExRoseTree{term: 4, children: []},
      %ExRoseTree{term: 5, children: []}
    ]
  },
  prev: [],
  next: [],
  path: [%ExRoseTree.Zipper.Location{prev: [], term: 1, next: []}]
}
@spec parent_location(t()) :: ExRoseTree.Zipper.Location.t() | nil

Returns the current Zipper's parent ExRoseTree.Zipper.Location.

examples

Examples

iex> loc_trees = for n <- [4,3,2,1], do: ExRoseTree.new(n)
...> locs = for n <- loc_trees, do: ExRoseTree.Zipper.Location.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, path: locs)
...> ExRoseTree.Zipper.parent_location(z)
%ExRoseTree.Zipper.Location{prev: [], term: 4, next: []}
@spec parent_term(t()) :: ExRoseTree.t() | nil

Returns the term in the current Zipper's parent ExRoseTree.Zipper.Location.

examples

Examples

iex> loc_trees = for n <- [4,3,2,1], do: ExRoseTree.new(n)
...> locs = for n <- loc_trees, do: ExRoseTree.Zipper.Location.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, path: locs)
...> ExRoseTree.Zipper.parent_term(z)
4

Link to this section Direct Descendants

@spec child_at(t(), non_neg_integer()) :: t() | nil

Moves focus to the child at the specified index. If there are no children, or if the child does not exist at the index, returns nil.

examples

Examples

iex> tree = ExRoseTree.new(5, [6,7,8,9])
...> z = ExRoseTree.Zipper.new(tree)
...> ExRoseTree.Zipper.child_at(z, 2)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 8, children: []},
  prev: [
    %ExRoseTree{term: 7, children: []},
    %ExRoseTree{term: 6, children: []}
  ],
  next: [%ExRoseTree{term: 9, children: []}],
  path: [%ExRoseTree.Zipper.Location{prev: [], term: 5, next: []}]
}
Link to this function

first_child(zipper, predicate \\ &Util.always/1)

View Source
@spec first_child(t(), ExRoseTree.predicate()) :: t() | nil

Moves focus to the first child. If there are no children, and this is a leaf, returns nil.

examples

Examples

iex> tree = ExRoseTree.new(5, [6,7,8,9])
...> z = ExRoseTree.Zipper.new(tree)
...> ExRoseTree.Zipper.first_child(z)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 6, children: []},
  prev: [],
  next: [
    %ExRoseTree{term: 7, children: []},
    %ExRoseTree{term: 8, children: []},
    %ExRoseTree{term: 9, children: []}
  ],
  path: [%ExRoseTree.Zipper.Location{prev: [], term: 5, next: []}]
}

iex> tree = ExRoseTree.new(5, [6,7,8,9])
...> z = ExRoseTree.Zipper.new(tree)
...> ExRoseTree.Zipper.first_child(z, fn x -> x.term == 9 end)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 9, children: []},
  prev: [
    %ExRoseTree{term: 8, children: []},
    %ExRoseTree{term: 7, children: []},
    %ExRoseTree{term: 6, children: []}
  ],
  next: [],
  path: [%ExRoseTree.Zipper.Location{prev: [], term: 5, next: []}]
}
Link to this function

first_grandchild(zipper, predicate \\ &Util.always/1)

View Source
@spec first_grandchild(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the first grandchild -- the first child of the first child -- of the focus. If there are no grandchildren, moves to the next sibling of the first child and looks for that tree's first child. This repeats until the first grandchild is found or it returns nil if none are found.

Link to this function

first_great_grandchild(zipper, predicate \\ &Util.always/1)

View Source
@spec first_great_grandchild(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the first great-grandchild -- the first child of the first grandchild -- of the focus. If there are no great-grandchildren, moves to the next sibling of the first grandchild and looks for that tree's first child. This repeats until the first great-grandchild is found or it returns nil if none are found.

Link to this function

last_child(zipper, predicate \\ &Util.always/1)

View Source
@spec last_child(t(), ExRoseTree.predicate()) :: t() | nil

Moves focus to the last child. If there are no children, and this is a leaf, returns nil.

examples

Examples

iex> tree = ExRoseTree.new(5, [6,7,8,9])
...> z = ExRoseTree.Zipper.new(tree)
...> ExRoseTree.Zipper.last_child(z)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 9, children: []},
  prev: [
    %ExRoseTree{term: 8, children: []},
    %ExRoseTree{term: 7, children: []},
    %ExRoseTree{term: 6, children: []}
  ],
  next: [],
  path: [%ExRoseTree.Zipper.Location{prev: [], term: 5, next: []}]
}
Link to this function

last_grandchild(zipper, predicate \\ &Util.always/1)

View Source
@spec last_grandchild(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the last grandchild -- the last child of the last child -- of the focus. If there are no grandchildren, moves to the previous sibling of the last child and looks for that tree's last child. This repeats until the first grandchild is found or it returns nil if none are found.

Link to this function

last_great_grandchild(zipper, predicate \\ &Util.always/1)

View Source
@spec last_great_grandchild(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the last great-grandchild -- the last child of the last grandchild -- of the focus. If there are no great-grandchildren, moves to the previous sibling of the last grandchild and looks for that tree's last child. This repeats until the last great-grandchild is found or it returns nil if none are found.

Link to this function

leftmost_descendant(zipper, predicate \\ nil)

View Source
@spec leftmost_descendant(t(), predicate() | nil) :: t() | nil

Descend the left-most edge until it can go no further or until the optional predicate matches. Does not include siblings of starting focus.

Link to this function

rightmost_descendant(zipper, predicate \\ nil)

View Source
@spec rightmost_descendant(t(), predicate() | nil) :: t() | nil

Descend the right-most edge until it can go no further or until the optional predicate matches. Does not include siblings of starting focus.

Link to this section Siblings

Link to this function

append_last_sibling(zipper, sibling)

View Source
@spec append_last_sibling(t(), term()) :: t()

Appends a new sibling to the Zipper's next siblings.

Link to this function

append_previous_sibling(zipper, sibling)

View Source
@spec append_previous_sibling(t(), term()) :: t()

Appends a new sibling to the Zipper's prev siblings.

Link to this function

first_sibling(zipper, predicate \\ &Util.always/1)

View Source
@spec first_sibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves focus to the first sibling from the current focus. If there are no more siblings before the current focus, returns nil.

examples

Examples

iex> prev = for n <- [1,2,3,4], do: ExRoseTree.new(n)
...> next = for n <- [6,7,8,9], do: ExRoseTree.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, prev: prev, next: next)
...> ExRoseTree.Zipper.first_sibling(z)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 1, children: []},
  prev: [],
  next: [
    %ExRoseTree{term: 2, children: []},
    %ExRoseTree{term: 3, children: []},
    %ExRoseTree{term: 4, children: []},
    %ExRoseTree{term: 5, children: []},
    %ExRoseTree{term: 6, children: []},
    %ExRoseTree{term: 7, children: []},
    %ExRoseTree{term: 8, children: []},
    %ExRoseTree{term: 9, children: []}
  ],
  path: []
}
Link to this function

insert_next_sibling_at(zipper, sibling, index)

View Source
@spec insert_next_sibling_at(t(), term(), integer()) :: t()

Inserts a new sibling in the Zipper's next siblings at the given index.

Link to this function

insert_previous_sibling_at(zipper, sibling, index)

View Source
@spec insert_previous_sibling_at(t(), term(), integer()) :: t()

Inserts a new sibling in the Zipper's prev siblings at the given index.

Link to this function

last_sibling(zipper, predicate \\ &Util.always/1)

View Source
@spec last_sibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves focus to the last sibling from the current focus. If there are no more siblings after the current focus, returns nil.

examples

Examples

iex> prev = for n <- [1,2,3,4], do: ExRoseTree.new(n)
...> next = for n <- [6,7,8,9], do: ExRoseTree.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, prev: prev, next: next)
...> ExRoseTree.Zipper.last_sibling(z)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 9, children: []},
  prev: [
    %ExRoseTree{term: 8, children: []},
    %ExRoseTree{term: 7, children: []},
    %ExRoseTree{term: 6, children: []},
    %ExRoseTree{term: 5, children: []},
    %ExRoseTree{term: 4, children: []},
    %ExRoseTree{term: 3, children: []},
    %ExRoseTree{term: 2, children: []},
    %ExRoseTree{term: 1, children: []}
  ],
  next: [],
  path: []
}
Link to this function

map_next_siblings(zipper, map_fn)

View Source
@spec map_next_siblings(t(), (ExRoseTree.t() -> ExRoseTree.t())) :: t()

Applies the given function to all next siblings of the current focus without moving the Zipper.

examples

Examples

iex> next = for n <- [6,7,8,9], do: ExRoseTree.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, next: next)
...> map_fn = &ExRoseTree.map_term(&1, fn term -> term * 2 end)
...> ExRoseTree.Zipper.map_next_siblings(z, &map_fn.(&1))
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 5, children: []},
  prev: [],
  next: [
    %ExRoseTree{term: 12, children: []},
    %ExRoseTree{term: 14, children: []},
    %ExRoseTree{term: 16, children: []},
    %ExRoseTree{term: 18, children: []}
  ],
  path: []
}
Link to this function

map_previous_siblings(zipper, map_fn)

View Source
@spec map_previous_siblings(t(), (ExRoseTree.t() -> ExRoseTree.t())) :: t()

Applies the given function to all previous siblings of the current focus without moving the Zipper.

examples

Examples

iex> prev = for n <- [1,2,3,4], do: ExRoseTree.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, prev: prev)
...> map_fn = &ExRoseTree.map_term(&1, fn term -> term * 2 end)
...> ExRoseTree.Zipper.map_previous_siblings(z, &map_fn.(&1))
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 5, children: []},
  prev: [
    %ExRoseTree{term: 8, children: []},
    %ExRoseTree{term: 6, children: []},
    %ExRoseTree{term: 4, children: []},
    %ExRoseTree{term: 2, children: []}
  ],
  next: [],
  path: []
}
Link to this function

next_sibling(zipper, predicate \\ &Util.always/1)

View Source
@spec next_sibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves focus to the next sibling of the current focus. If there are no more siblings after the current focus, returns nil.

examples

Examples

iex> prev = for n <- [1,2,3,4], do: ExRoseTree.new(n)
...> next = for n <- [6,7,8,9], do: ExRoseTree.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, prev: prev, next: next)
...> ExRoseTree.Zipper.next_sibling(z)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 6, children: []},
  prev: [
    %ExRoseTree{term: 5, children: []},
    %ExRoseTree{term: 4, children: []},
    %ExRoseTree{term: 3, children: []},
    %ExRoseTree{term: 2, children: []},
    %ExRoseTree{term: 1, children: []}
  ],
  next: [
    %ExRoseTree{term: 7, children: []},
    %ExRoseTree{term: 8, children: []},
    %ExRoseTree{term: 9, children: []}
  ],
  path: []
}
@spec next_siblings(t()) :: [ExRoseTree.t()]

Returns the siblings that come after the current focus.

examples

Examples

iex> next = for t <- [6,7,8,9], do: ExRoseTree.new(t)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, next: next)
...> ExRoseTree.Zipper.next_siblings(z)
[
  %ExRoseTree{term: 6, children: []},
  %ExRoseTree{term: 7, children: []},
  %ExRoseTree{term: 8, children: []},
  %ExRoseTree{term: 9, children: []}
]
Link to this function

pop_first_sibling(zipper)

View Source
@spec pop_first_sibling(t()) :: {t(), ExRoseTree.t() | nil}

Removes the first sibling from the Zipper.

Link to this function

pop_last_sibling(zipper)

View Source
@spec pop_last_sibling(t()) :: {t(), ExRoseTree.t() | nil}

Removes the last sibling from the Zipper.

Link to this function

pop_next_sibling(zipper)

View Source
@spec pop_next_sibling(t()) :: {t(), ExRoseTree.t() | nil}

Removes the next sibling from the Zipper.

Link to this function

pop_next_sibling_at(zipper, index)

View Source
@spec pop_next_sibling_at(t(), integer()) :: {t(), ExRoseTree.t() | nil}

Removes a sibling from the Zipper's next siblings at the given index.

Link to this function

pop_previous_sibling(zipper)

View Source
@spec pop_previous_sibling(t()) :: {t(), ExRoseTree.t() | nil}

Removes the previous sibling from the Zipper.

Link to this function

pop_previous_sibling_at(zipper, index)

View Source
@spec pop_previous_sibling_at(t(), integer()) :: {t(), ExRoseTree.t() | nil}

Removes a sibling from the Zipper's prev siblings at the given index.

Link to this function

prepend_first_sibling(zipper, sibling)

View Source
@spec prepend_first_sibling(t(), term()) :: t()

Prepends a new sibling to the Ziper's prev siblings.

Link to this function

prepend_next_sibling(zipper, sibling)

View Source
@spec prepend_next_sibling(t(), term()) :: t()

Prepends a new sibling to the Zipper's next siblings.

Link to this function

previous_sibling(zipper, predicate \\ &Util.always/1)

View Source
@spec previous_sibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves focus to the previous sibling to the current focus. If there are no more siblings before the current focus, returns nil.

examples

Examples

iex> prev = for n <- [1,2,3,4], do: ExRoseTree.new(n)
...> next = for n <- [6,7,8,9], do: ExRoseTree.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, prev: prev, next: next)
...> ExRoseTree.Zipper.previous_sibling(z)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 4, children: []},
  prev: [
    %ExRoseTree{term: 3, children: []},
    %ExRoseTree{term: 2, children: []},
    %ExRoseTree{term: 1, children: []}
  ],
  next: [
    %ExRoseTree{term: 5, children: []},
    %ExRoseTree{term: 6, children: []},
    %ExRoseTree{term: 7, children: []},
    %ExRoseTree{term: 8, children: []},
    %ExRoseTree{term: 9, children: []}
  ],
  path: []
}
Link to this function

previous_siblings(zipper)

View Source
@spec previous_siblings(t()) :: [ExRoseTree.t()]

Returns the siblings that come before the current focus.

examples

Examples

iex> prev = for t <- [1,2,3,4], do: ExRoseTree.new(t)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, prev: prev)
...> ExRoseTree.Zipper.previous_siblings(z)
[
  %ExRoseTree{term: 1, children: []},
  %ExRoseTree{term: 2, children: []},
  %ExRoseTree{term: 3, children: []},
  %ExRoseTree{term: 4, children: []}
]
Link to this function

sibling_at(zipper, index)

View Source
@spec sibling_at(t(), non_neg_integer()) :: t() | nil

Moves focus to the sibling of the current focus at the given index. If no sibling is found at that index, or if the provided index is the index for the current focus, returns nil.

examples

Examples

iex> prev = for n <- [1,2,3,4], do: ExRoseTree.new(n)
...> next = for n <- [6,7,8,9], do: ExRoseTree.new(n)
...> tree = ExRoseTree.new(5)
...> z = ExRoseTree.Zipper.new(tree, prev: prev, next: next)
...> ExRoseTree.Zipper.sibling_at(z, 2)
%ExRoseTree.Zipper{
  focus: %ExRoseTree{term: 3, children: []},
  prev: [
    %ExRoseTree{term: 2, children: []},
    %ExRoseTree{term: 1, children: []}
  ],
  next: [
    %ExRoseTree{term: 4, children: []},
    %ExRoseTree{term: 5, children: []},
    %ExRoseTree{term: 6, children: []},
    %ExRoseTree{term: 7, children: []},
    %ExRoseTree{term: 8, children: []},
    %ExRoseTree{term: 9, children: []}
  ],
  path: []
}

Link to this section Niblings: Nieces & Nephews

Link to this function

first_descendant_nibling(zipper, predicate \\ &Util.always/1)

View Source
@spec first_descendant_nibling(t(), predicate()) :: t() | nil

Recursively searches the descendant branches of the first sibling for the first "descendant nibling" of the current focus. That is, if a first nibling is found, it will then look for the first child of that tree (the "descendant nibling"). It will repeat the search if one is found, and it will continue until no more are found, returning the last one visited.

Link to this function

first_extended_nibling(zipper, predicate \\ &Util.always/1)

View Source
@spec first_extended_nibling(t(), ExRoseTree.predicate()) :: t() | nil

Searches for the first child of the first extended cousin--aka, the first extended nibling--of the focused tree.

Link to this function

first_nibling(zipper, predicate \\ &Util.always/1)

View Source
@spec first_nibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the first nibling -- the first child of the first sibling with children -- before the current focus. If not found, returns nil.

Link to this function

first_nibling_at_sibling(zipper, index, predicate \\ &Util.always/1)

View Source
@spec first_nibling_at_sibling(t(), non_neg_integer(), ExRoseTree.predicate()) ::
  t() | nil

Moves the focus to the first nibling for a specific sibling -- the first child of the sibling at the given index -- of the current focus. If not found, returns nil.

Link to this function

last_descendant_nibling(zipper, predicate \\ &Util.always/1)

View Source
@spec last_descendant_nibling(t(), predicate()) :: t() | nil

Recursively searches the descendant branches of the last sibling for the last "descendant nibling" of the current focus. That is, if a last nibling is found, it will then look for the last child of that tree (the "descendant nibling"). It will repeat the search if one is found, and it will continue until no more are found, returning the last one visited.

Link to this function

last_extended_nibling(zipper, predicate \\ &Util.always/1)

View Source
@spec last_extended_nibling(t(), ExRoseTree.predicate()) :: t() | nil

Searches for the last child of the last extended cousin--aka, the last extended nibling--of the focused tree.

Link to this function

last_nibling(zipper, predicate \\ &Util.always/1)

View Source
@spec last_nibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the last nibling -- the last child of the last sibling with children -- before the current focus. If not found, returns nil.

Link to this function

last_nibling_at_sibling(zipper, index, predicate \\ &Util.always/1)

View Source
@spec last_nibling_at_sibling(t(), non_neg_integer(), ExRoseTree.predicate()) ::
  t() | nil

Moves the focus to the last nibling for a specific sibling -- the last child of the sibling at the given index -- of the current focus. If not found, returns nil.

Link to this function

next_descendant_nibling(zipper, predicate \\ &Util.always/1)

View Source
@spec next_descendant_nibling(t(), predicate()) :: t() | nil

Recursively searches the descendant branches of the next sibling for the next "descendant nibling" of the current focus. That is, if a next nibling is found, it will then look for the first child of that tree (the "descendant nibling"). It will repeat the search if one is found, and it will continue until no more are found, returning the last one visited.

Link to this function

next_extended_nibling(zipper, predicate \\ &Util.always/1)

View Source
@spec next_extended_nibling(t(), ExRoseTree.predicate()) :: t() | nil

Searches for the first child of the next extended cousin--aka, the next extended nibling--of the focused tree.

Link to this function

next_grandnibling(zipper, predicate \\ &Util.always/1)

View Source
@spec next_grandnibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the next grand-nibling -- the first grandchild of the next sibling -- of the current focus. If not found, returns nil.

Link to this function

next_nibling(zipper, predicate \\ &Util.always/1)

View Source
@spec next_nibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the next nibling -- the first child of the first next sibling with children -- before the current focus. If not found, returns nil.

Link to this function

previous_descendant_nibling(zipper, predicate \\ &Util.always/1)

View Source
@spec previous_descendant_nibling(t(), predicate()) :: t() | nil

Recursively searches the descendant branches of the previous sibling for the previous "descendant nibling" of the current focus. That is, if a previous nibling is found, it will then look for the last child of that tree (the "descendant nibling"). It will repeat the search if one is found, and it will continue until no more are found, returning the last one visited.

Link to this function

previous_extended_nibling(zipper, predicate \\ &Util.always/1)

View Source
@spec previous_extended_nibling(t(), ExRoseTree.predicate()) :: t() | nil

Searches for the last child of the previous extended cousin--aka, the previous extended nibling--of the focused tree.

Link to this function

previous_grandnibling(zipper, predicate \\ &Util.always/1)

View Source
@spec previous_grandnibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the previous grand-nibling -- the last grandchild of the previous sibling -- of the current focus. If not found, returns nil.

Link to this function

previous_nibling(zipper, predicate \\ &Util.always/1)

View Source
@spec previous_nibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the previous nibling -- the last child of the first previous sibling with children -- before the current focus. If not found, returns nil.

Link to this section Piblings: Aunts & Uncles

Link to this function

first_ancestral_pibling(zipper, predicate \\ &Util.always/1)

View Source
@spec first_ancestral_pibling(t(), ExRoseTree.predicate()) :: t() | nil

Recursively searches the path for the first, first "ancestral" pibling. That is, if a first pibling is not found for the parent, it will search the grandparent. If one is not found for the grandparent, it will search the great-grandparent. And so on, until it reaches the root. If the root is reached and it does not have a first pibling, the function returns nil.

Link to this function

first_extended_pibling(zipper, predicate \\ &Util.always/1)

View Source
@spec first_extended_pibling(t(), ExRoseTree.predicate()) :: t() | nil

Searches for the first extended cousin of the parent--aka, the first extended pibling--of the focused tree.

Note: Extended Pibling here really means parent-cousin n-times removed, and is a bit of a neolism, since pibling technically means parent-sibling.

Link to this function

first_grandpibling(zipper, predicate \\ &Util.always/1)

View Source
@spec first_grandpibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the first grandpibling -- the first sibling of the grandparent -- of the current focus. If not found, returns nil.

Link to this function

first_pibling(zipper, predicate \\ &Util.always/1)

View Source
@spec first_pibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the first pibling -- the first sibling of the parent -- of the current focus. If not found, returns nil.

Link to this function

last_ancestral_pibling(zipper, predicate \\ &Util.always/1)

View Source
@spec last_ancestral_pibling(t(), ExRoseTree.predicate()) :: t() | nil

Recursively searches the path for the first, last "ancestral" pibling. That is, if a last pibling is not found for the parent, it will search the grandparent. If one is not found for the grandparent, it will search the great-grandparent. And so on, until it reaches the root. If the root is reached and it does not have a last pibling, the function returns nil.

Link to this function

last_extended_pibling(zipper, predicate \\ &Util.always/1)

View Source
@spec last_extended_pibling(t(), ExRoseTree.predicate()) :: t() | nil

Searches for the last extended cousin of the parent--aka, the last extended pibling--of the focused tree.

Note: Extended Pibling here really means parent-cousin n-times removed, and is a bit of a neolism, since pibling technically means parent-sibling.

Link to this function

last_grandpibling(zipper, predicate \\ &Util.always/1)

View Source
@spec last_grandpibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the last grandpibling -- the last sibling of the grandparent -- of the current focus. If not found, returns nil.

Link to this function

last_pibling(zipper, predicate \\ &Util.always/1)

View Source
@spec last_pibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the last pibling -- the last sibling of the parent -- of the current focus. If not found, returns nil.

Link to this function

next_ancestral_pibling(zipper, predicate \\ &Util.always/1)

View Source
@spec next_ancestral_pibling(t(), ExRoseTree.predicate()) :: t() | nil

Recursively searches the path for the first, next "ancestral" pibling. That is, if a next pibling is not found for the parent, it will search the grandparent. If one is not found for the grandparent, it will search the great-grandparent. And so on, until it reaches the root. If the root is reached and it does not have a next pibling, the function returns nil.

Link to this function

next_extended_pibling(zipper, predicate \\ &Util.always/1)

View Source
@spec next_extended_pibling(t(), ExRoseTree.predicate()) :: t() | nil

Searches for the next extended cousin of the parent--aka, the next extended pibling--of the focused tree.

Note: Extended Pibling here really means parent-cousin n-times removed, and is a bit of a neolism, since pibling technically means parent-sibling.

Link to this function

next_grandpibling(zipper, predicate \\ &Util.always/1)

View Source
@spec next_grandpibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the next grandpibling -- the next sibling of the grandparent -- of the current focus. If not found, returns nil.

Link to this function

next_pibling(zipper, predicate \\ &Util.always/1)

View Source
@spec next_pibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the next pibling -- the next sibling of the parent -- of the current focus. If not found, returns nil.

Link to this function

pibling_at(zipper, index)

View Source
@spec pibling_at(t(), non_neg_integer()) :: t() | nil

Moves the focus to the pibling of the current focus at the given index. If no pibling is found at that index, returns nil.

Link to this function

previous_ancestral_pibling(zipper, predicate \\ &Util.always/1)

View Source
@spec previous_ancestral_pibling(t(), ExRoseTree.predicate()) :: t() | nil

Recursively searches the path for the first, previous "ancestral" pibling. That is, if a previous pibling is not found for the parent, it will search the grandparent. If one is not found for the grandparent, it will search the great-grandparent. And so on, until it reaches the root. If the root is reached and it does not have a previous pibling, the function returns nil.

Link to this function

previous_extended_pibling(zipper, predicate \\ &Util.always/1)

View Source
@spec previous_extended_pibling(t(), ExRoseTree.predicate()) :: t() | nil

Searches for the previous extended cousin of the parent--aka, the previous extended pibling--of the focused tree.

Note: Extended Pibling here really means parent-cousin n-times removed, and is a bit of a neolism, since pibling technically means parent-sibling.

Link to this function

previous_grandpibling(zipper, predicate \\ &Util.always/1)

View Source
@spec previous_grandpibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the previous grandpibling -- the previous sibling of the grandparent -- of the current focus. If not found, returns nil.

Link to this function

previous_pibling(zipper, predicate \\ &Util.always/1)

View Source
@spec previous_pibling(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the previous pibling -- the previous sibling of the parent -- of the current focus. If not found, returns nil.

Link to this section First Cousins

Link to this function

first_first_cousin(zipper, predicate \\ &Util.always/1)

View Source
@spec first_first_cousin(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the first first-cousin -- the first child of the first pibling with children -- of the current focus. If not found, returns nil.

Link to this function

last_first_cousin(zipper, predicate \\ &Util.always/1)

View Source
@spec last_first_cousin(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the last first-cousin -- the last child of the last pibling with children -- of the current focus. If not found, returns nil.

Link to this function

next_first_cousin(zipper, predicate \\ &Util.always/1)

View Source
@spec next_first_cousin(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the next first-cousin -- the first child of the next pibling with children -- of the current focus. If not found, returns nil.

Link to this function

previous_first_cousin(zipper, predicate \\ &Util.always/1)

View Source
@spec previous_first_cousin(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the previous first-cousin -- the last child of the previous pibling with children -- of the current focus. If not found, returns nil.

Link to this section Second Cousins

Link to this function

first_second_cousin(zipper, predicate \\ &Util.always/1)

View Source
@spec first_second_cousin(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the first second-cousin -- the first grandchild of the first grandpibling with grandchildren -- of the current focus. If not found, returns nil.

Link to this function

last_second_cousin(zipper, predicate \\ &Util.always/1)

View Source
@spec last_second_cousin(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the last second-cousin -- the last grandchild of the last grandpibling with grandchildren -- of the current focus. If not found, returns nil.

Link to this function

next_second_cousin(zipper, predicate \\ &Util.always/1)

View Source
@spec next_second_cousin(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the next second-cousin -- the first grandchild of the next grandpibling with grandchildren -- of the current focus. If not found, returns nil.

Link to this function

previous_second_cousin(zipper, predicate \\ &Util.always/1)

View Source
@spec previous_second_cousin(t(), ExRoseTree.predicate()) :: t() | nil

Moves the focus to the previous second-cousin -- the last grandchild of the previous grandpibling with grandchildren -- of the current focus. If not found, returns nil.

Link to this section Extended Cousins

Link to this function

first_extended_cousin(zipper, predicate \\ &Util.always/1)

View Source
@spec first_extended_cousin(t(), ExRoseTree.predicate()) :: t() | nil

Searches for the first extended cousin or the first first-cousin of the focused tree.

High level steps:

  1. Ascend path to find highest ExRoseTree.Zipper.Location with prev siblings.
  2. Starting with the first sibling, check each subtree from left to right, and if you reach the target depth and find a tree that satisifies any given predicate, stop there. Otherwise, continue left to right.
  3. If you return back to the starting ExRoseTree.Zipper.Location, descend the path to next deepest ExRoseTree.Zipper.Location and set as starting ExRoseTree.Zipper.Location. Goto step 2.
  4. If you return back to starting ExRoseTree.Zipper.Location, and it is also the ending ExRoseTree.Zipper.Location, and you have not found a suitable note at the right depth, you will not find one.
Link to this function

last_extended_cousin(zipper, predicate \\ &Util.always/1)

View Source
@spec last_extended_cousin(t(), ExRoseTree.predicate()) :: t() | nil

Searches for the last extended cousin or the last first-cousin of the focused tree.

Link to this function

next_extended_cousin(zipper, predicate \\ &Util.always/1)

View Source
@spec next_extended_cousin(t(), ExRoseTree.predicate()) :: t() | nil

Searches for the next extended cousin or the next first-cousin of the focused tree.

Link to this function

previous_extended_cousin(zipper, predicate \\ &Util.always/1)

View Source
@spec previous_extended_cousin(t(), ExRoseTree.predicate()) :: t() | nil

Searches for the previous extended cousin or the previous first-cousin of the focused tree.