Clojure core.logic.Могу ли я использовать сложные структуры данных в фактах и ​​правилах? - PullRequest
0 голосов
/ 25 октября 2018

Я пытаюсь разобраться с core.logic.

Могу ли я использовать сложные структуры данных в фактах и ​​правилах?

Например, я пытаюсь это сделать:

(pldb/db-rel test a)

(defn is-wibble? [a] (= true (:wibble a)))

(def facts
  (pldb/db
   [test {:name "x" :wibble true}]
   [test {:name "y" :wibble false}]
   [test {:name "z" :wibble true}]))

(defn -main [& args]
  (doseq [x
          (pldb/with-db facts
            (run* [q]
              (is-wibble? q)))]
    (println x))))

Но выдает ошибку:

Caused by: java.lang.ClassCastException: java.base/java.lang.Boolean cannot be cast to clojure.lang.IFn
    at clojure.core.logic.Substitutions.bind(logic.clj:425)
    at polvo.core$_main$fn__377$fn__378$fn__379$_inc__380.invoke(core.clj:223)

На самом деле в строке

(is-wibble? q)

Я ошибаюсь, пытаясь создать правила как обычные функции?Или поставить сложные данные в факты?

1 Ответ

0 голосов
/ 25 октября 2018

Вы можете исследовать сложные структуры данных в вашем db, единственная недостающая часть здесь - это то, что в вашем предикате is-wibble? вы получите логическую переменную вместо фактического, конкретного значения.

В core.logic есть цель pred, которая будет project lvar, чтобы вы могли проверить ее значение.Я переименовал цель, чтобы соответствовать типичным именам целей.pred принимает lvar и некоторую функцию, которая получит значение lvar, и цель pred успешна, если эта функция предиката возвращает истину-y.

(defn wibbleo [a] (pred a :wibble))

Или вы можете определить это так, используяисходный предикат:

(defn wibbleo [a] (pred a is-wibble?))    

Обратите внимание, что вы также должны включить свой db-rel в качестве цели (test q), тогда ваша программа должна работать:

(pldb/with-db facts
  (run* [q]
    (test q)
    (wibbleo q)))
=> ({:name "x", :wibble true} {:name "z", :wibble true})
...