   opposite direction, construct a lens that focuses and updates
   a converted value."
   [one->other other->one]
-  (lens
-   one->other
-   (fn [s f]
-     (other->one (f (one->other s))))))
+  (lens one->other
+        (fn [s f]
+          (other->one (f (one->other s))))))
 
 ;; lenses
 


(def tail
  "A lens into the tail of a collection."
  (lens
   rest
   (fn [s f]
     (into (sequential-empty s)
           (cons (first s)
                 (f (rest s)))))))

(defn key
  "Given a key, returns a lens that focuses on the given key of
  an associative data structure."
  [k]
  (lens
   (fn [s]
     (get s k))
   (fn [s f]
     (update s k f))))

(def ^:private core-select-keys
  #?(:clj clojure.core/select-keys
     :cljs cljs.core/select-keys))

(defn select-keys
  "Return a lens focused on the given keys in an associative data
  structure."
  [ks]
  (lens
   (fn [s]
     (core-select-keys s ks))
   (fn [s f]
     (merge (apply dissoc s ks)
            (-> (core-select-keys s ks)
                f
                (core-select-keys ks))))))

(defn in
  "Given a path and optionally a default value, return a lens that
  focuses the given path in an associative data structure."
  ([path]
   (in path nil))
  ([path default]
   (lens
    (fn [s]
      (get-in s path default))
    (fn [s f]
      (update-in s path f)))))

;; interop

(defn- prefix-key
  {:internal true :no-doc true}
  [key id]
  (keyword (str id "-" (name key))))

(def ^:private +empty+
  #?(:clj (Object.) :cljs (js/Object.)))

#?(:clj
   (deftype RWFocus [id lens src equals?


  The lens is not well-behaved, depens on the outcome of the predicate."
  [applies?]
  (lens (fn [s]
          (when (applies? s)
            s))
        (fn [s f]
          (if (applies? s)
            (f s)
            s))))

(defn nth
  "Given a number, returns a lens that focuses on the given index of
  a collection."
  [n]
  (lens (fn [s] (c/nth s n))
        (fn [s f] (update s n f))))

(def fst (nth 0))
(def snd (nth 1))

(defn- sequential-empty
  [coll]
  (cond
    (map? coll) {}
