 
   Treeish-2-3
   (split [this pred] (rope-split this pred))
-  (conc [this tree] (concat this tree))
+  (conc [this tree] (cat this tree))
   (left [_] left)
   (right [_] right)
   (depth [_] level)

            (let [[_ part1 right-rope position1] (rope-split-at root start)
                  length (- end start)
                  rest (- (count part1) position1)]
              (cond (= length (+ rest (count right-rope))) (conc (core/subs part1 position1) right-rope)
                    (> length rest)
                    (let [[middle-rope part2 _ position2] (rope-split-at right-rope (- length rest))]
                      (conc (core/subs part1 position1) (conjoin middle-rope (core/subs part2 0 position2))))
                    :default (core/subs part1 position1 (+ position1 length))))))))

(defn delete
  "Delete the characters at interval [start..end] in the Rope"
  [root start end]
  {:pre [(>= (- end start) 0)]}
  (cond
   (= start end) root
   (= end (count root))
   (let [[left-rope part _ position] (rope-split-at root start)]
     (conjoin left-rope (core/subs part 0 position)))
   :default
   (let [[left-rope part1 _ position1] (rope-split-at root start)
         [_ part2 right-rope position2] (rope-split-at root end)]
     (conc (conjoin left-rope (core/subs part1 0 position1) (core/subs part2 position2))
           right-rope))))

(deftype Rope [#^CharSequence left #^CharSequence right #^CharSequenceMeasurement weight #^int level]
  Measurable

             (recur (cons current acc) rest (fib-border length))))
          (fold acc))))))

(defmethod cat :default [coll1 coll2]
  (let [new-rope (rope coll1 coll2)]
    (if (balanced? new-rope)
      new-rope
      (rebalance new-rope))))

(defn string->rope [string]
  "Create a fresh Rope from flat string.
The resulting leafes will carry at most *leaf-cutoff-length* characters of the
input string."
  (letfn [(build [acc]
            (if (> (count acc) 1)
              (recur (->> (partition-all 2 acc) (map #(apply rope %))))
              (first acc)))]
    (->> (partition-all (-> (count string) (/ (.. Runtime getRuntime availableProcessors)) int) string)
         (pmap (bound-fn [chunk]
                 (->> (partition-all *leaf-cutoff-length* chunk) (map #(apply str %)) build)))
         build rope)))

(defmethod cat [String String] [string1 string2]
  (let [string (str string1 string2)]
    (if (> (count string) *leaf-cutoff-length*)
     (string->rope string)
     string)))

(defn rope-split
  "Split Rope at root by calling pred against the accumulated weights and nodes traversed so far

Pred should evaluate to a truthy value whenever the weight or node should be
traversed to the right, i.e. towards higher weights.
The vector returned is composed of the re-evaluated tree to the left of the
split, the actual split leaf, a reassembled tree of the nodes cut off to the
right of the traversal and the measurement traversed, i.e. the weight of the
left tree plus the split leaf."
  [root pred]
  (let [reassemble (fn [coll]
                     (if (empty? coll)
                       (rope)
                       (->> coll (reduce conc) rope)))]
    (loop [acc (), zipper (rope-zip (if (zero? (count root)) (rope "") root)),
           total-weight (measurement)]
      (let [node (zip/node zipper), node-weight (measure node), new-weight (measure+ node-weight total-weight)]
        (if (string? node)
          (if (pred new-weight node)
            (throw (IndexOutOfBoundsException. (str "Node index out of range: " (pr-str new-weight))))
            [(-> zipper zip/remove zip/root), node, (reassemble acc), new-weight])
          (let [left (zip/down zipper), right (zip/right left)]
            (cond (nil? right) (recur acc left total-weight)
                  (pred new-weight node) (recur acc right new-weight)
                  :default
                  (recur (cons (zip/node right) acc)
                         (-> right (zip/replace nil) zip/left)
                         total-weight))))))))

;; Presumably faster than iterating till zip/end?
(defn conjoin
  "conj for Ropes. x is concatenated to the depth-first end, i.e. rightmost node of the Rope

Additional xs will be concatenated first."
  ([root x]
     (loop [zipper (rope-zip root)]
