   [name namespaces]
   (first-non-nil (map (partial find-name-in-namespace name) namespaces)))
 
-
 (defn create-from-template
   "Searches for a template file (with a .cml extension) as a classpath resource in one of the namespaces,
-creating a function (using the factory) if found. If not found, throws RuntimeException."
+creating a function (using the factory) if found, or nil."
   [name namespaces factory-fn]
-  (let [file (str name ".cml")
-        template-fn (first-non-nil
-      (for [namespace namespaces]
-        (if-let [src (find-namespace-resource namespace file)]
-          (factory-fn namespace src))))]
-
-    (or
-      template-fn
-      (throw (RuntimeException.
-        (format "Could not locate function %s or template '%s' in %s %s."
-          name file
-          (if (= 1 (count namespaces)) "namespace" "namespaces")
-          (to-str-list (map ns-name namespaces))))))))
+  (let [file (str name ".cml")]
+    (first-non-nil (for [namespace namespaces]
+                     (if-let [src (find-namespace-resource namespace file)]
+                       (factory-fn namespace src))))))
 
 (defn find-or-create-fn
   "Searches for an existing function in any of the namespaces, or creates a function from a bare template."


(defn get-or-create-cached-fn
  "Gets a view or fragment function from a cache, or finds it as a real function,
or uses the factory function to create it dynamically (from a template)."
  [name cache config-key factory-fn]
  (if-let [existing (get @cache name)]
    existing
    (let [namespaces (get configuration config-key)
          created (find-or-create-fn name namespaces factory-fn)]
      (swap! cache assoc name created)
      created)))

(defn get-fragment
  "Gets a fragment function with a given string name. Fragment functions expect an env and a params and return a seq of rendered DOM nodes."
  [name]
  (get-or-create-cached-fn name fragment-cache :fragment-namespaces parse-and-create-fragment))

(defn get-view
  "Gets a fragment function with a given string name. View functions expect an env and return a seq of rendered DOM nodes."
  [name]
  (get-or-create-cached-fn name view-cache :view-namespaces parse-and-create-view))
(def expansion-re #"\$((\(.*?\)))")

(defn extract-matched-expression
  "Extracts the expression string from a matched expansion."
  [#^MatchResult match-result]
  (.group match-result 2)) 


; TODO: Eventually, when we have (defview) and (deffragment), we may need two levels of cache:
