   ([lens src {:keys [read-only? check-equals?]
               :or {read-only? false
                    check-equals? true}}]
-   (let [id (str (gensym "lentes"))]
+   (let [id (str (gensym "lentes"))
+         cache (volatile! +empty+)
+         srccache (volatile! @src)]
      (if read-only?
-       (ROFocus. id lens src check-equals?)
-       (RWFocus. id lens src check-equals?)))))
-
-(defn focus-atom
-  "A deprecated alias for `derive`."
-  {:deprecated true}
-  [lens source]
-  (derive lens source nil))
+       (ROFocus. id lens src srccache cache check-equals?)
+       (RWFocus. id lens src srccache cache check-equals?)))))

                                     (cb key self old' new')))))))
     (removeWatch [_ key]
       (let [key (prefix-key key id)]
         (remove-watch source key))))

   :cljs
   (deftype RWFocus [id lens source check-equals?]
     IAtom
     IDeref
     (-deref [_] (focus lens @source))

     IReset
     (-reset! [self newval]
       (swap! source #(put lens newval %))
       (deref self))

     ISwap
     (-swap! [self f]
       (swap! source (fn [s] (over lens f s)))
       (deref self))
     (-swap! [self f x]
       (swap! source (fn [s] (over lens #(f % x) s)))
       (deref self))
     (-swap! [self f x y]
       (swap! source (fn [s] (over lens #(f % x y) s)))
       (deref self))
     (-swap! [self f x y more]
       (swap! source (fn [s] (over lens #(apply f % x y more) s)))
       (deref self))

     IWatchable
     (-add-watch [self key cb]
       (let [key (prefix-key key id)]
         (add-watch source key (fn [key _ oldval newval]
                                 (let [old' (focus lens oldval)
                                       new' (focus lens newval)]
                                   (when (or (not check-equals?)

  [key id]
  (keyword (str id "-" (name key))))

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

#?(:clj
   (deftype RWFocus [id lens src srccache cache check-equals?]
     clojure.lang.IDeref
     (deref [it]
       (letfn [(generate []
                 (let [source (deref src)
                       result (focus lens source)]
                   (vreset! srccache source)
                   (vreset! cache result)
                   result))]
         (locking it
           (if (identical? @cache +empty+)
             (generate)
             (if (identical? @srccache @src)
               @cache
               (generate))))))

     clojure.lang.IAtom
     (reset [self newval]
       (swap! src #(put lens newval %))
       (deref self))
     (swap [self f]
       (swap! src (fn [s] (over lens f s)))
       (deref self))
     (swap [self f x]
       (swap! src (fn [s] (over lens #(f % x) s)))
       (deref self))
     (swap [self f x y]
       (swap! src (fn [s] (over lens #(f % x y) s)))
       (deref self))
     (swap [self f x y more]
       (swap! src (fn [s] (over lens #(apply f % x y more) s)))
       (deref self))

     clojure.lang.IRef
     (addWatch [self key cb]
       (let [key (prefix-key key id)]
         (add-watch src key (fn [key _ oldval newval]
                                 (let [old' (focus lens oldval)
                                       new' (focus lens newval)]
                                   (when (or (not check-equals?)
