                                      (cb key self old' new')))))))
      (-remove-watch [_ key]
        (let [key (prefix-key key id)]
-         (remove-watch source key)))))
-
+         (remove-watch src key)))))
+
+(def ^:private not-identical? (complement identical?))
+(def ^:private empty-cache? #(identical? @% +empty+))
 
 #?(:clj
-   (deftype ROFocus [id lens source check-equals?]
+   (deftype ROFocus [id lens src srccache cache check-equals?]
      clojure.lang.IDeref
-     (deref [_] (focus lens @source))
+     (deref [_]
+       (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.IRef
      (addWatch [self key cb]
        (let [key (prefix-key key id)]
-         (add-watch source key (fn [key _ oldval newval]
+         (add-watch src key (fn [key _ oldval newval]
                                  (let [old' (focus lens oldval)
                                        new' (focus lens newval)]
                                    (when (or (not check-equals?)

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

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

     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?)

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

(defn derive
  "Create a derived atom from an other atom with the provided lense.
