 (extend-type String
   Treeish-2-3
   (split [_ _] nil)
-  (conc [this coll] (concat this coll))
+  (conc [this coll] (cat this coll))
   (left [_] nil)
   (right [_] nil)
   (depth [_] 0))

(ns engine.data.rope
  "Implementation of Ropes as per \"Ropes: an Alternative to Strings\"
by Boehm, Hans-J; Atkinson, Russ; and Plass, Michael (December 1995), doi:10.1002/spe.4380251203."
  (:use [clojure.core :exclude [concat subs]]
        [clojure.string :only [join]])
  (:require [clojure.zip :as zip]
            [clojure.core :as core])
  (:import [clojure.lang Counted Indexed]
           [java.lang String IndexOutOfBoundsException]))

(doseq [fun ['concat 'subs]] (ns-unmap *ns* fun))

(def *fib-seq* (map first (iterate (fn [[a b]] [b (+ a b)]) [0 1])))
(def *leaf-cutoff-length* 128) ; TODO make constant in clojure 1.3

(defprotocol Measurable
  "Trivial protocol for things measurable.

  [x]
  (satisfies? Measurable x))

(defn measure+
  "Add up weights of measurements"
  [& xs]
  (->> xs (map vals) (reduce #(map + %1 %2)) (apply measurement)))

(defrecord CharSequenceMeasurement [#^int length #^int lines])

(defmethod print-method CharSequenceMeasurement [weight writer]
  (print-simple (format "#<CharSequenceMeasurement %d/%d>" (:length weight) (:lines weight)) writer))

(defn measurement
  "CharSequenceMeasurement from length and lines; (measurement) is 0/0"
  ([] (CharSequenceMeasurement. 0 0))
  ([length lines] (CharSequenceMeasurement. length lines)))

(defn count-matches
  "Number of character matches in string"
