Generic zipper implementation in Erlang.

Zippers: what are they good for?

Zippers let you traverse immutable data structures with ease and flexibility.

Contact Us

For questions or general comments regarding the use of this library, please use our public hipchat room.

If you find any bugs or have a problem while using this library, please open an issue in this repo (or a pull request :)).

And you can check all of our open-source projects at inaka.github.io

Usage

For a map tree structure like the following:

Root = #{type => planet,
         attrs => #{name => "Earth"},
         children => [
           #{type => continent,
             attrs => #{name => "America"},
             children => [
               #{type => country,
                 attrs => #{name => "Argentina"},
                 children => []},
               #{type => country,
                 attrs => #{name => "Brasil"},
                 children => []}
             ]
            },
           #{type => continent,
             attrs => #{name => "Europe"},
             children => [
               #{type => country,
                 attrs => #{name => "Sweden"},
                 children => []},
               #{type => country,
                 attrs => #{name => "England"},
                 children => []}
             ]
            }
         ]
        },

You can build a zipper by providing three simple functions:

This is an example of how you would define a zipper and then use it to traverse the map tree structure above:

%% Create the zipper
IsBranchFun = fun
                  (#{children := [_ | _]}) -> true;
                  (_) -> false
              end,
ChildrenFun = fun(Node) -> maps:get(children, Node) end,
MakeNodeFun = fun(Node, Children) -> Node#{children => Children} end,
Zipper = zipper:new(fun is_map/1, ChildrenFun, MakeNodefun, Root),

%% Traverse the zipper with next
Zipper1 = zipper:next(Zipper),
Zipper2 = zipper:next(Zipper),

%% Get the current zipper node
Argentina = zipper:node(Zipper2).
io:format("~p", [Argentina]),
%%= #{type => country,
%%=   attrs => #{name => "Argentina"},
%%=   children => []}

%% Go up and get the node
Zipper3 = zipper:up(Zipper2).
America = zipper:node(Zipper2).
io:format("~p", [America]),
%%= #{type => country,
%%=   attrs => #{name => "America"},
%%=   children => [#{...}, #{...}]}

References