ExZipper

An Elixir implementation of Huet's Zipper1, with gratitude to Rich Hickey's Clojure implementation2.

Installation

@deps [
  ex_zipper: "~> 0.1.3"
]

Usage

Below is an outline of the API provided by ExZipper.Zipper. See the full documentation here for usage examples

Creating zippers

ExZipper provides one zipper construction function for working with plain lists, ExZipper.Zipper.list_zipper/1

iex> Zipper.list_zipper([1,[],2,[3,[4,5]]])

For more complex cases, ExZipper.Zipper.zipper/4 provides a mechanism to define your own zipper, passing for its first three arguments functions to

  1. determine whether a node is a branch
  2. return the children of a branch node
  3. create a new node from an existing node and a new set of children

and your root data structure as its fourth argument.

For example, to create a zipper for a data structure of nested maps, where a branch's children are defined under the :kids key:

  iex> Zipper.zipper(
  ...>   fn node -> is_map(node) and Map.has_key?(node, :kids) end,
  ...>   fn %{kids: kids} -> kids end,
  ...>   fn node, new_kids -> %{node | kids: new_kids} end,
  ...>   %{ value: "top", kids: [%{value: "first inner"}, %{value: "last inner}]}
  ...> )

Navigating zippers

The following functions move through a zipper and return either a new zipper, or an error of the form {:error, :atom_describing_the_error}

The following functions move through a zipper via a depth-first walk. That is, moving as deep down one branch of the tree before moving laterally.

Editing zippers

The following functions modify the zipper without shifting focus away from the current node. They will return a zipper, or an error, if called with an invalid zipper as input (for example, trying to insert a child into a leaf node)

Helper functions

License

Standard MIT. See LICENSE.md


Created: 2017-11-16Z