这是我在Datomic google论坛上提出的问题的重新发布( see here - last 3 posts are best )。
这个问题围绕着我动态生成Datomic查询的事实。因此,在传递给函数之前,参数(名称和值)的数量是未知的。我可以很好地生成查询。核心问题是,使用Clojure Datomic API,我无法使用动态数量的参数调用 datomic.api / q 函数。因此,下面的 〜@ unquote-splice 表达式失败。我尝试了其他几种方法,包括 部分 和 应用 ,但无济于事。
(def expression-final `(datomic.api/q ~expression-intermediate ~db-conn ~@param-values)) ;; gives the error in question
(eval expression-final)
java.lang.Exception: processing rule: (q__34868 ?e)
at datomic.datalog$eval_rule$fn__4687.invoke(datalog.clj:977)
at datomic.datalog$eval_rule.invoke(datalog.clj:957)
at datomic.datalog$eval_query.invoke(datalog.clj:999)
at datomic.datalog$qsqr.invoke(datalog.clj:1053)
at datomic.datalog$qsqr.invoke(datalog.clj:1021)
at datomic.query$q.invoke(query.clj:453)
at datomic.api$q.doInvoke(api.clj:31)
... 1 stack levels elided ...
at user$eval34866.invoke(crud_spec.clj:32)
... 3 stack levels elided ...
at stefon_datomic.crud$retrieve_entity.invoke(crud.clj:95)
...
Caused by: java.lang.Exception: processing clause: [?e :posts/title (quote ?title)] ;; this fails with or without the (quote ...)
at datomic.datalog$eval_clause$fn__4667.invoke(datalog.clj:934)
at datomic.datalog$eval_clause.invoke(datalog.clj:900)
at datomic.datalog$eval_rule$fn__4687.invoke(datalog.clj:972)
at datomic.datalog$eval_rule.invoke(datalog.clj:957)
...
Caused by: java.lang.UnsupportedOperationException: nth not supported on this type: Symbol
... 2 stack levels elided ...
at datomic.datalog$extrel_coll$fn__4384.invoke(datalog.clj:197)
... 4 stack levels elided ...
at datomic.datalog$iterator.invoke(datalog.clj:30)
我想知道这是否是Datomic Clojure API中的错误?或者,如果有更简单的方法来传递动态数量的变量。硬编码传入的变量数量,无法动态生成查询。请参阅最后的 3 posts here ,以获取更多详细信息。
由于
答案 0 :(得分:6)
因此,基于您的源代码,我设法简化了代码:
(defn add-entity-ns
[ekey datom-map]
(reduce-kv (fn [a k v]
(assoc a (keyword
(name ekey)
(name k))
v))
{}
datom-map))
(defn retrieve-entity
[conn constraint-map]
(let [name-fn (comp symbol
(partial str "?")
name)
param-names (map name-fn
(keys constraint-map))
param-vals (vals constraint-map)
constraint-map (add-entity-ns :posts constraint-map)
where-clause (map #(vector '?e % %2)
(keys constraint-map)
param-names)
in-clause (conj param-names '$)
final-clause (concat [:find '?e]
[:in] in-clause
[:where] where-clause)]
(apply d/q final-clause (d/db conn) param-vals)))
注意:当我开始使用datomic时,我自己写了类似的函数来生成查询。我最终将它们扔掉了,原因有几个:
filter
过滤掉哪些帖子符合您的条件,依此类推。如果您有一个大型数据库,请使用带有foldcat
的缩减器。答案 1 :(得分:2)
好的,我在Datomic Google网上论坛上解决了这个问题( see here )。基本上, fig.1 有效。而且,我能够运行生成的代码( fig.2 ),而无需引入可怕的引用。希望这有助于其他人。
(datomic.api/q '{:find [?e]
:in [$ [?title ?content-type]]
:where [[?e :posts/title ?title] [?e :posts/content-type ?content-type]]}
(datomic.api/db conn)
["t" "c/t"])
图1
(datomic.api/q expression-intermediate-0 (datomic.api/db conn) (into [] param-values))
图2