3

以下を生成する必要があります。

(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])]))

「applyor」を使用する別の方法はありますか?

ありがとう。

4

2 に答える 2

4

問題は、マクロが関数ではないことです。マクロはコンパイル時に実行され、実際の構文(主にリストとシンボル)が渡されるため、実行時に実行時のデータ構造に適用することはできません。したがって、(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で、に置き換えるclojureql.predicatesと、ファイルの残りの部分の代わりに[clojurecl.predicates :as qlp]使用できます。これにより、上記のようになります(も置き換えた場合)。qlpclojureql.predicatesclojureql.coreqlc

(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* ...)。clojureqlwhereはanyandを置き換え、andorを認識します。したがって、この置き換えを自分で行うと機能するはずですclojureql.predicates/and*。とはclojureql.or*両方とも関数であり、マクロではないため、問題はありません。and*or*

于 2012-02-07T22:30:56.650 に答える
1

提供するパラメーターの量orがわかっている場合、これがおそらく最も簡単な解決策です。

(apply #(or %1 %2) [nil 10]) ; => 10
于 2012-02-07T20:38:01.257 に答える