Internal implementation of the MBQL | (ns metabase.lib.util.match.impl) |
Return a function to use for pattern matching via (Class-based matching currently only works in Clojure. For ClojureScript, only predicate function matching works.) have to do this at runtime because we don't know if a symbol is a class or pred or whatever when we compile the macro | (defn match-with-pred-or-class
[pred-or-class]
(cond
;; If this function is ever used from JS, we need to figure out how to do this
#?@(:clj [(class? pred-or-class)
(partial instance? pred-or-class)])
(fn? pred-or-class)
pred-or-class
:else
;; this is dev-specific so we don't need to localize it
(throw (ex-info "Invalid pattern: don't know how to handle symbol." {:symbol pred-or-class})))) |
Internal impl for | (defn match-in-collection
[match-fn clause-parents form]
{:pre [(fn? match-fn) (vector? clause-parents)]}
(cond
(map? form)
(reduce-kv (fn [acc k v]
(if-let [match (match-fn (conj clause-parents k) v)]
;; Deliberately not using into to avoid converting to transient and back.
(reduce conj acc match)
acc))
[] form)
(sequential? form)
(let [fst (first form)
k (if (keyword? fst)
(conj clause-parents fst)
clause-parents)]
(reduce (fn [acc v]
(if-let [match (match-fn k v)]
(reduce conj acc match)
acc))
[] form)))) |
Inernal impl for | (defn replace-in-collection
[replace-fn clause-parents form]
(cond
(map? form)
(reduce-kv (fn [form k v]
(assoc form k (replace-fn (conj clause-parents k) v)))
form form)
(sequential? form)
(mapv (partial replace-fn (if (keyword? (first form))
(conj clause-parents (first form))
clause-parents))
form)
:else form)) |
Like | (defn update-in-unless-empty
[m ks f & args]
(if-not (seq (get-in m ks))
m
(apply update-in m ks f args))) |