Xipper

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

Zippers provide an elegant solution for traversing a tree-like data structure, while maintaining enough state data to reconstruct the entire tree from any of its child nodes.

All that is required to create a zipper for a data structure is the data structure itself and a set of functions that define behaviours around nodes of the data structure. See below and the documentation for Xipper.new/4 for details.

Basic Usage and API Reference

For more complete documentation and examples, see the documentation for Xipper either inline in the file here, or on hexdocs.pm.

Creating a zipper

For a nested list data structure

zipper = Xipper.new(
  # root data structure
  [1, 2, [3, [4, 5], 6], [], 7],

  # function for determining whether a node is a branch
  &is_list/1,

  # function for returning a branch node's children
  fn branch_node -> branch_node end,

  # function for creating a new node from an existing node and a list of children
  fn _node, children -> children end
)

For a map data structure

zipper = Xipper.new(
  %{name: "a", children: [%{name: "b"}, %{name: "c"}]},

  fn branch -> is_map(branch) && Map.has_key?(branch, :children) end,

  fn branch -> Map.get(branch, :children) end,

  fn
    node = %{children: _}, children -> %{node | children: children}
    node, children -> Map.put(node, :children, children)
  end
)

Querying a zipper

Navigating a zipper

Modifying a zipper

Installation

If available in Hex, the package can be installed by adding xipper to your list of dependencies in mix.exs:

def deps do
  [
    {:xipper, "~> 0.1.0"}
  ]
end

Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/xipper.