    (instance? String s) (java.io.StringReader. s)
    :else (throw (Exception. (format "can't turn %s into a Reader" s)))))
 
-(defn- %positioned-stream [reader δposition encoder line-offset column-offset]
+(defn- %positioned-stream [reader delta-position encoder line-offset column-offset]
   (lazy-seq
    (if-let [char (read-char reader)]
-     (cons [char (+ line-offset (:line δposition)) (+ column-offset (:column δposition))]
+     (cons [char (+ line-offset (:line delta-position)) (+ column-offset (:column delta-position))]
            (%positioned-stream
-            reader (inc-δposition δposition char encoder) encoder line-offset column-offset)))))
+            reader (inc-delta-position delta-position char encoder) encoder line-offset column-offset)))))
 
 (defn positioned-stream
   ([input]

      (.encode (java.nio.CharBuffer/wrap (char-array [char])))
      (.limit)))

;; A δposition is a difference in position from a block of text.
(def null-δposition
  {:byte 0 :char 0 :line 0 :column 0 :tab-lead nil
   :starts-with-newline? false :ends-with-return? false })

(defn %normal-char-δposition [length]
  {:byte length :char 1 :line 0 :column 1 :tab-lead nil
   :starts-with-newline? false :ends-with-return? false })

(def %normal-char-δposition-vec
  (into [] (for [i (range 1 7)] (%normal-char-δposition i))))

(def %normal-char-δposition-1
  (%normal-char-δposition-vec 0))

(defn normal-char-δposition
  ([l] (%normal-char-δposition-vec (dec l)))
  ([] %normal-char-δposition-1))

(def return-δposition
  {:byte 1 :char 1 :line 1 :column 0 :tab-lead nil
   :starts-with-newline? false :ends-with-return? true})

(def newline-δposition
  {:byte 1 :char 1 :line 1 :column 0 :tab-lead nil
   :starts-with-newline? true :ends-with-return? false})

(def formfeed-δposition
  ;; hack: formfeed has zero width.
  ;; Maybe add state so it resets the column?
  {:byte 1 :char 1 :line 0 :column 0 :tab-lead nil
   :starts-with-newline? true :ends-with-return? false})

(def tab-δposition
  {:byte 1 :char 1 :line 0 :column 0 :tab-lead 0
   :starts-with-newline? false :ends-with-return? false})

(defn combine-δposition
  ([] null-δposition)
  ([x] x)
  ([x y] (let [{xb :byte xc :char xln :line xco :column xt :tab-lead
                xn :starts-with-newline? xr :ends-with-return?} x

;; (inheriting this behavior or lack thereof from java.io.LineNumberingReader).
;; If you care about tab width, use this delta-position library instead.
;;
;; A delta-position is a map representing how a given string affects the position.
;; Importantly, combining two delta-position is associative
;; — it's not merely a position that you have to compute from the beginning
;; of the file, but a delta that you can compute between arbitrary points.
;;
;; Thus, if you want fast random access to the line and column
;; information from a random byte or character position in your file,
;; you can divide your file in chunks of strings,
;; compute delta-position for each chunk in parallel,
;; and build a tree index that makes it easy to
;; compute the position of a random character or byte.
;; Of course, if you're using a variable length encoding,
