Skip to content

Instantly share code, notes, and snippets.

@joelittlejohn
Created February 26, 2013 21:58
Show Gist options
  • Save joelittlejohn/5042641 to your computer and use it in GitHub Desktop.
Save joelittlejohn/5042641 to your computer and use it in GitHub Desktop.
BrisFunctional zipper
(ns brisfunctional-zipper.core)
(def sample
[:+ [:* 5 6] [:* 7 4] [:+ 1 2]])
(defn loc [l r c p]
{:left l
:right r
:cur c
:path p})
(defn edit [t]
(loc nil (rest t) (first t) nil))
(defn left [{:keys [left right cur path]}]
(loc (rest left) (cons cur right) (first left) path))
(defn right [{:keys [left right cur path]}]
(loc (cons cur left) (rest right) (first right) path))
(defn down [{:keys [left right cur path]}]
(loc nil (rest cur) (first cur) (cons [left right] path)))
(defn up [{:keys [left right cur path]}]
(let [[pleft pright] (first path)
newcur (concat (reverse left) (cons cur right))]
(loc pleft pright newcur (rest path))))
(defn update [f {:keys [left right cur path]}]
(loc left right (f cur) path))
(defn top [{:keys [left right cur path] :as node}]
(if (seq path)
(recur (up node))
node))
(defn out [loc]
(-> loc top up :cur))
@jan-g
Copy link

jan-g commented Feb 27, 2013

The only note I'll make is that we really should have defined edit as follows:

(loc nil nil t nil)

... which makes 'out' look a little more sane (no superfluous 'up').

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment