我需要生成以下代码:
(clojureql.core/join (clojureql.core/table db :tableA) (clojureql.core/table db :tableA)
(clojureql.core/where (apply and (= :tableA.id :tableB.id)
[(apply or [(clojureql.predicates/in :tableA.id [1 2])
(clojureql.predicates/in :tableA.id [3 4])])])))但“应用或”形式需要从另一个函数或宏“传递”。我的意思是:
(clojureql.core/join (clojureql.core/table db :tableA) (clojureql.core/table db :tableA)
(clojureql.core/where (apply and (= :tableA.id :tableB.id)
[(my-or-f)])))其中,此函数为:
(defn my-or-f []
(apply or [(clojureql.predicates/in :tableA.id [1 2])
(clojureql.predicates/in :tableA.id [3 4])]))然而,这个函数抛出了这个异常:
#<CompilerException java.lang.Exception: Can't take value of a macro: #'clojure.core/or (NO_SOURCE_FILE:2)>我也尝试过使用宏。它可以编译,但当我尝试使用此宏运行查询时,它会抛出相同的异常
(defmacro my-or-f []
`(apply or [(clojureql.predicates/in :tableA.id [1 2])
(clojureql.predicates/in :tableA.id [3 4])]))有没有其他方式可以让我使用“应用或者”?
谢谢。
发布于 2012-02-08 06:30:57
问题是宏不是函数-它们在编译时运行,并被传递给实际的语法(主要是列表和符号),因此您不能在运行时将它们应用于运行时数据结构。因此,(apply or my-list)抛出一个错误。您有几个选项:
(def my-list (list false false 4 false 5))
(some identity my-list) -- returns 4
(reduce #(or %1 %2) my-list) -- returns 4在实践中,您可能需要some --它在到达返回true的元素时立即停止,而reduce总是遍历整个列表。
注意:您的(apply and ...)也会遇到同样的问题-- (every? identity ...)将做您想做的事情。
然而,在这种情况下,为什么需要使用apply呢?这应该也能很好地工作:
(clojureql.core/join (clojureql.core/table db :tableA) (clojureql.core/table db :tableA)
(clojureql.core/where (and (= :tableA.id :tableB.id)
(my-or-f))))
(defn my-or-f []
(or (clojureql.predicates/in :tableA.id [1 2])
(clojureql.predicates/in :tableA.id [3 4])))最后一个建议-当你require clojureql.predicates时,如果你用[clojurecl.predicates :as qlp]代替clojureql.predicates,你可以在文件的其余部分用qlp代替clojureql.predicates,这就是上面(如果我们也用qlc代替clojureql.core ):
(qlc/join (qlc/table db :tableA) (qlc/table db :tableA)
(qlc/where (and (= :tableA.id :tableB.id)
(my-or-f))))
(defn my-or-f []
(or (qlp/in :tableA.id [1 2])
(qlp/in :tableA.id [3 4])))读起来容易多了。
对于ClojureQL,可以尝试使用(apply clojureql.predicates/or* ...)和(apply clojureql.predicates/and* ...)。clojureql的where用clojureql.predicates/and*和clojureql.or*替换了它看到的任何and和or,所以您自己做这个替换应该是可行的。and*和or*都是函数,而不是宏,所以应该不会有任何问题。
发布于 2012-02-08 04:38:01
如果您为or提供的参数数量是已知的,这可能是最简单的解决方案:
(apply #(or %1 %2) [nil 10]) ; => 10https://stackoverflow.com/questions/9181231
复制相似问题