Skip to content

Commit

Permalink
Var resolution for query fns/preds when in JVM (tonsky#178)
Browse files Browse the repository at this point in the history
This commit adds a reader conditional to enable the use of
namespace-qualified symbols as query functions or predicates, when in
JVM Clojure. This allows queries using functions or predicates to be
reused between Datomic and DataScript when running on the JVM.

The semantics of a DataScript query are otherwise unchanged; global var
resolution is only attempted as a final step before failure.

The semantics when operating in a ClojureScript context are entirely
unchanged, since global symbol->var resolution is not supported.
  • Loading branch information
levand authored and tonsky committed Sep 15, 2016
1 parent e9a6b67 commit 587e1e1
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/datascript/query.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -430,10 +430,16 @@
args)]
(apply f resolved-args))))

(defn- resolve-sym [sym]
#?(:cljs nil
:clj (when (namespace sym)
(when-let [v (resolve sym)] @v))))

(defn filter-by-pred [context clause]
(let [[[f & args]] clause
pred (or (get built-ins f)
(context-resolve-val context f)
(resolve-sym f)
(when (nil? (rel-with-attr context f))
(throw (ex-info (str "Unknown predicate '" f " in " clause)
{:error :query/where, :form clause, :var f}))))
Expand All @@ -449,6 +455,7 @@
binding (dp/parse-binding out)
fun (or (get built-ins f)
(context-resolve-val context f)
(resolve-sym f)
(when (nil? (rel-with-attr context f))
(throw (ex-info (str "Unknown function '" f " in " clause)
{:error :query/where, :form clause, :var f}))))
Expand Down
10 changes: 10 additions & 0 deletions test/datascript/test/query_fns.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,13 @@
:where [(fun ?e) ?x]]
[1]))))

(def sample-query-fn (constantly 42))

(deftest test-symbol-resolution
(let [q '[:find ?x .
:where [(datascript.test.query-fns/sample-query-fn) ?x]]]
#?(:clj
(is (= 42 (d/q q [1])))
:cljs
(is (thrown-with-msg? ExceptionInfo #"Unknown function"
(d/q q [1]))))))

0 comments on commit 587e1e1

Please sign in to comment.