      (if (= start (count root))
        "" ; For consistency with "normal" subs
        (let [[_ string right-rope position] (rope-split-at root start)]
-         (str (core/subs string position) right-rope))))
+         (conc (core/subs string position) right-rope))))
   ([root start end]
      {:pre [(>= (- end start) 0)]}
-     (if (= start (count root))
-       ""
-       (let [[_ part1 right-rope position1] (rope-split-at root start)
-             length (- end start)
-             rest (- (count part1) position1)]
-         (if (> length rest)
-           (let [[middle-rope part2 _ position2] (rope-split-at right-rope (- length rest))]
-             (str (core/subs part1 position1) middle-rope (core/subs part2 0 position2)))
-           (core/subs part1 position1 (+ position1 length)))))))
+     (let [length (count root)]
+      (cond (= start length) ""
+            (> end length) (throw (IndexOutOfBoundsException. (str "Rope index out of range: " end)))
+            :default
+            (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)]}
-  (if (= end (count root))
-    (let [[left-rope part _ position] (rope-split-at root start)]
-      (conjoin left-rope (core/subs part 0 position)))
-    (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))))
+  (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

              (if (<= weight l-index)
                (recur (zip/right next) (- l-index weight))
                (recur next l-index)))
            :default (throw (IndexOutOfBoundsException. (str "String index out of range: " index)))))))

(defn rope-seq
  "Lazy sequence of all Rope nodes at root, depth-first order"

(defn rope->string
  "Flat string from Rope at root"
  [root]
  (apply str (->> (rope-seq root) (filter string?))))

(defn rebalance
  "Create rebalanced copy of the Rope, using the algorithm described in \"Ropes: an Alternative to Strings\".
