Created
March 11, 2014 20:10
-
-
Save renegr/9493967 to your computer and use it in GitHub Desktop.
Functional Zippers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns tree | |
(:require [clojure.zip :as zip])) | |
(defn make-zip | |
"Returns a zipper for a given datastructure" | |
[root] | |
(zip/zipper (complement string?) | |
(comp seq :children) | |
(fn [node children] | |
(assoc node :children children)) | |
root)) | |
(defn find-by-id | |
"Finds an element by it's id. | |
Returns a vector [element zip-loc]." | |
[root id] | |
(loop [loc (make-zip root)] | |
(let [found? (when (= (-> loc zip/node :id) id) (zip/node loc))] | |
(if (or (zip/end? loc) found?) | |
(if found? [found? loc] nil) | |
(recur (zip/next loc)))))) | |
(defn transact! | |
"Finds <id> then applies <f> to node & returns the updated tree." | |
[root id f] | |
(if-let [[elm loc] (find-by-id root id)] | |
(-> (zip/edit loc f) zip/root) | |
root)) | |
(comment | |
"Usage Example:" | |
(def sample {:name "A" | |
:id 1 | |
:children [{:name "B" | |
:id 2 | |
:children []} | |
{:name "C" | |
:id 3 | |
:children [{:name "D" :id 4 :children []}]}]}) | |
(transact! sample 2 #(assoc % :name "Z"))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment