Использование спецификации Clojure с объектами Datomic

#clojure #datomic #clojure.spec

#clojure #datomic #clojure.spec

Вопрос:

Допустим, у меня есть следующие спецификации:

 (s/def :person/age number?)
(s/def :person/name string?)

(s/def ::person (s/keys :req [:person/name :person/age]))
  

Затем я извлекаю объект из Datomic:

 (def person-entity (d/entity (d/db conn) [:person/name "Mr entity"]))
  

Если я попытаюсь проверить соответствие спецификации, это не удастся, потому что объекты не являются картами:

 (s/explain ::person person-entity)

val: #:db{:id 17592186069950} fails spec: :some-ns/person predicate: map?
  

В моем приложении есть функции, которые принимают сущности в качестве аргументов, и я хотел бы избежать необходимости везде привязывать объекты к картам, чтобы заставить спецификацию работать в разработке.

Как мне выполнить проверку объектов через спецификацию?

Комментарии:

1. Хороший вопрос. После того, как вы найдете решение этой проблемы, не столкнетесь ли вы также с проблемой с пространствами имен? Сопоставление объектов будет выглядеть примерно так: {:person/name "Mr. Entity"} , который не проверяется (s/keys :req [::name ::age]) , если только эти определения не находятся внутри (ns person) . Но это заставляет вас определять кучу пространств имен пакетов верхнего уровня, что не кажется разумным.

2. Спасибо @Marc, я обновил пример.

Ответ №1:

Хотя верно, что ваши пространства имен немного ограничены (вы должны использовать :person /name вместо ::name ), в спецификации также есть ограничение, которое может быть снято. В настоящее время s / keys требует, чтобы все входные коллекции соответствовали clojure.core/keys предикату. Объекты Datomic не являются картами и поэтому не проходят эту проверку (и, следовательно, ошибка в отношении map? предиката).

Я отправил отчет об ошибке здесь: http://dev.clojure.org/jira/browse/CLJ-2041 Не стесняйтесь голосовать / следить за билетом, если хотите.