   (cons (first dtree)
     (map f (rest dtree))))
 
-
 (defn tree-get
   "Given some item from a duffel tree, either a file or another tree, returns
   the value of a key in it"

  [dir]
  (-> dir create-dir-tree explode-tree))

(defn tree-dir-mapreduce
  "Given a duffel tree, runs f on each dir map (the first item in each list).
  The first argument to f is the dir map itself. The second is an accumulator.
  The third is the list of file maps for that dir map. f returns a vector of the
  new dir map and new accumulator which will be given to all child calls from
  that dir. If the new dir map is nil then that dir is removed and its children
  are not processed. The file map list is unaffected"
  [f acc dtree]
  (let [dir-map (first dtree)
        file-maps (rest dtree)
        [new-dir-map new-acc] (f dir-map acc file-maps)]
    (when-not (nil? new-dir-map)
      (cons new-dir-map
        (remove nil?
          (map
            #(if (sequential? %) (tree-dir-mapreduce f new-acc %) %)
            file-maps))))))

(defn tree-file-map
  "Given a duffel tree, runs f on each file map (any map that's not the first
  item in a list). The first argument to f is the dir map for the file, the
  second is the file map currently being looked at. f returns the new file map
  to be put in place. If f returns nil then the file map will be ommitted from
  the returned tree"
  [f dtree]
  (let [dir-map (first dtree)
        file-maps (rest dtree)]
    (cons dir-map
      (remove nil?
        (map
          #(if (sequential? %) (tree-file-map f %) (f dir-map %))
          file-maps)))))

(defn tree-map
  "Given a duffel tree, run f on that duffel tree. Look through the returned
  duffel tree for more duffel trees, and call f on them. Recurse."

  (if (sequential? el)
    (cons (apply assoc (first el) kvs) (rest el))
    (apply assoc el kvs)))
