Определение компонентов запроса журнала данных за пределами (datomic.api/q '[])

Я работаю с datomic.api от clojure. Я хочу реорганизовать несколько сложный запрос журнала данных, такой как этот:

(datomic.api/q '[:find [?value ...] :in $ ?uid ?component :where
                [...some clause...]
                [...some other clause...]
                (or-join [?entitlement ?component]
                         (and [...some conditional stuff...])
                         (and [...some other conditional stuff...]))]
                db uid component)

... во что-то более читаемое. Мое желание состоит в том, чтобы локально связать (and...) компоненты запроса внутри let и ссылаться на них по имени внутри списка журнала данных. Вот так:

(datomic.api/q '[:find [?value ...] :in $ ?uid ?component :where
                [...some clause...]
                [...some other clause...]
                (or-join [?entitlement ?component]
                         entitled-for-component
                         entitled-for-application)]
                db uid component)

Различные кавычки в let (и раскаты внутри списка datomic.api/q) не работали. Какие-либо предложения?


person Dave Owens    schedule 05.08.2015    source источник
comment
Ага. Подход с кавычками/без кавычек работает, если вы используете синтаксические кавычки, но тогда вы закончите тем, что такие вещи, как и, будут заменены символами с указанием пространства имен, которые разобьют его по-другому. Ваш ответ ниже - это способ сделать это.   -  person Tony K.    schedule 05.08.2015
comment
Мне нравится ответ ниже, чтобы использовать правила. Чтобы квазицитировать в Clojure, как в других lisp, попробуйте форму template в обратной кавычке.   -  person Greg Hendershott    schedule 07.04.2016


Ответы (1)


Datomic использует правила для решения этой проблемы.

Datomic datalog позволяет упаковывать наборы предложений :where в именованные правила. Эти правила делают логику запроса многократно используемой, а также компонуемой, что означает, что вы можете связывать части логики запроса во время запроса.

Наборы правил определяются как список списков, которые затем используются в качестве дополнительных входных данных с datomic.api/q, привязанным к символу %.

(def rules [[(name-for-id restaurant-id?)
             [restaurant-id? :restaurant/name name?]]])

(datomic.api/q '[:find ?name . :in $ % ?restaurant-id :where
                 (name-for-id restaurant-id?)] db rules 42)

=> "Milliways"

Обратите внимание, что datomic.api/q ожидает правило набор, передача одного правила не будет работать.

Первый список в правиле определяет имя правила как первый элемент, за которым следует один или несколько параметров. Последующие векторы содержат одно или несколько предложений :where.

Также,

Как и в других предложениях where, вы можете указать базу данных перед именем правила, чтобы применить правило к этой базе данных. Базы данных нельзя использовать в качестве аргументов в правиле.

person Dave Owens    schedule 05.08.2015