 ;;                     v)
 ;;               data))))
 
+(defn- plus-yank [data lenses]
+  (map yank
+       (repeat data)
+       lenses))
+(defn- plus-shove [data v lenses]
+  (reduce (fn [data [l v]] (shove data l v))
+          data
+          (map vector lenses v)))
+
 (defn ++
   "Returns a lens over some data structure that shows a sequence of
   elements that each of the given lenses show on that. Note that the
   behaviour is undefined if those lenses do not show distrinct parts
   of the data structure."
   [& lenses]
-  (lens (fn [data] (map #(yank %1 %2)
-                       (repeat data)
-                       lenses))
-        (fn [data v] (reduce (fn [data [l v]] (shove data l v))
-                            data
-                            (map vector lenses v)))))
-
-
+  (lens plus-yank
+        plus-shove
+        lenses))
+
+(defn- at-index-shove [coll v n]
+  (let [[front back] (split-at n coll)]
+    (concat front
+            [v]
+            (rest back))))
 
 (defn at-index
   "Returns a lens that focuses on the value at position n in a sequence.
   The sequence must have >= n elements."
   [n]
-  (lens (fn [coll] (nth coll n))
-        (fn [coll v]
-          (let [[front back] (split-at n coll)]
-            (concat front
-                    [v]
-                    (rest back))))))
+  (lens nth
+        at-index-shove
+        n))

           %1
           (seq %2))))

(defn contains
  "Returns a lens showing the membership of the given value in a set."
  [v]
  (lens #(contains? % v)
        #(if %2
           (conj %1 v)
           (disj %1 v))))

(def ^{:doc "A lens that views a sequence of pairs as a map."}
  as-map
  (xmap #(into {} %) seq))

(defn member
  "Returns a lens showing the value mapped to the given key in a map,
  not-found or nil if key is not present. Note that when not-found (or
  nil) is shoved into the map, the association is removed."
  [key & [not-found]]
  (lens #(get % key not-found)
        #(if (= %2 not-found)
           (dissoc %1 key)
           (assoc %1 key %2))))

(def ^{:doc "A trivial lens that just shows nil over anything, and does never change anything."}
  void
  (lens (constantly nil) (fn [data _] data)))

(defn is
  "Returns a lens showing if a data structure equals the non-nil value v."
  [v]
  (assert (not (nil? v)))
  (lens #(= % v)
        #(if %2
           v
           (if (= %1 v)
             nil
             %1))))

(defn **
  "Return the product of several lenses, which means that each lens is
  held over an element of a collection in the order they appear in the
  argument list."
  [& lenses]
  (lens (fn [data] (map #(yank %1 %2)
                       data lenses))
        (fn [data v] (map #(shove %1 %2 %3)
                         data lenses v))))

;; not very general: 
;; (defn repeated

          reacl.lens/>>."}
  id (xmap identity identity))

(defn- comb-yank [data l1 l2]
  (yank (yank data l1) l2))
(defn- comb-shove [data v l1 l2]
  (shove data l1 (shove (yank data l1) l2 v)))

(defn- >>2
  [l1 l2]
  (lens comb-yank comb-shove l1 l2))

(defn >>
  "Returns a concatenation of two or more lenses, so that the combination shows the
