This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-10-12
Channels
- # announcements (13)
- # aws (18)
- # babashka (60)
- # babashka-sci-dev (83)
- # beginners (32)
- # biff (18)
- # calva (22)
- # cider (8)
- # clj-on-windows (101)
- # clojure (59)
- # clojure-bay-area (2)
- # clojure-europe (36)
- # clojure-india (4)
- # clojure-nl (3)
- # clojure-norway (5)
- # clojure-spec (4)
- # clojure-uk (1)
- # clojurescript (5)
- # conjure (1)
- # core-async (10)
- # cursive (7)
- # data-science (5)
- # datahike (10)
- # datalog (11)
- # datomic (3)
- # docker (3)
- # figwheel-main (2)
- # gratitude (3)
- # improve-getting-started (1)
- # introduce-yourself (5)
- # jobs (3)
- # joyride (12)
- # leiningen (1)
- # lsp (67)
- # malli (27)
- # off-topic (36)
- # random (1)
- # rdf (1)
- # re-frame (17)
- # reagent (21)
- # reitit (4)
- # releases (4)
- # remote-jobs (2)
- # ring (2)
- # sci (35)
- # shadow-cljs (28)
- # sql (3)
- # squint (9)
- # tools-deps (11)
Hello ๐
To include a literal, is it best to use :fn
?
In these examples I want to limit the matches to a specific value.
This seems to work:
((ma/parser [:fn #{1}]) 1)
;=> 1
((ma/parser [:* [:cat [:fn #{1}] [:fn #{2}]]])
[1 2 1 2 1 2])
;=> [[1 2] [1 2] [1 2]]
Does this seem like the correct approach?I would probably use [:= 1]
personally, but your approach seems fine, too.
Can I instrument protocol methods with Malli? We use protocols (implemented by records) quite a lot. With Spec we add an indirection via a regular function to have something to hang Clojure Spec specs off of. Is that what Iโd do with Malli too?
Ambrose was looking into this https://blog.ambrosebs.com/2022/09/08/schema-defprotocol.html https://clojurians.slack.com/archives/C06MAR553/p1661105488092049
Thank you!
Hi, I was curious if anyone has any pointers/implementation on validating EntityMap
using Malli . These are returned by (datomic.api/entity db entity-id)
.
These EntityMap
objects don't implement IPersistentMap
so schema like [:map ...]
fails with type mismatch.
I would greatly appreciate the inputs.
You can create your own schema type using -simple-schema
(here are some examples: https://github.com/metosin/malli/blob/1a9b3767f1d64d504663ca151363244db2635708/src/malli/core.cljc#L660)
I'm not sure on the details but I think you can make your predicate function convert the entity to a hashmap and then leverage the existing :map
schema type by having your custom schema type pass its arguments to the :map
type
Thanks @U051V5LLP I will give it a shot.
I have reached till below and was wondering how to pass the arguments to the :map
type.
(defn entity?
[entity]
(instance? datomic.query.EntityMap entity))
(defn -entitiy-map-schema
[]
(-simple-schema
{:type :entity-map
:pred entity?
:type-properties {:decode/map #(if (entity? %)
(into {} %)
%)}}))
On a sidenote, since a instances of datomic.query.EntityMap
may have nested datomic.query.EntityMap
, I think using a ::ref
would also be needed?hmm, I think it might not be as simple as using -simple-schema
you may have to copy the -map-schema
implementation and delegate to that, here is a heavily hacked one I got working but gives the general idea:
(defn -entity-map-schema
([]
(-entity-map-schema {:naked-keys true}))
([opts] ;; :naked-keys, :lazy
^{:type ::into-schema}
(reify
m/IntoSchema
(-type [_] :entity-map)
(-type-properties [_])
(-properties-schema [_ _])
(-children-schema [_ _])
(-into-schema [parent {:keys [closed] :as properties} children options]
(let [map-schema (m/schema (into [:map] children))
entry-parser (m/-create-entry-parser children opts options)
cache (m/-create-cache options)]
^{:type ::schema}
(reify
m/AST
(m/-to-ast [this _] (m/-to-ast map-schema _))
m/Schema
(-validator [this]
(let [keyset (m/-entry-keyset (m/-entry-parser this))
_ (println "2 " (m/children map-schema))
validators (map
(fn [[key {:keys [optional]} value]]
(let [valid? (m/-validator value)
default (boolean optional)]
(fn [m] (if-let [map-entry (find m key)]
(valid? (val map-entry))
default))))
(m/children map-schema))
validate (apply every-pred validators)]
;; THIS LINE IS THE SIGNIFICANT CHANGE:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(fn [m] (and
(instance? datomic.query.EntityMap m)
(validate (into {} m))))))
(-explainer [this path] (m/-explainer map-schema path))
(-parser [this] (m/-parser map-schema))
(-unparser [this] (m/-unparser map-schema))
(-transformer [this transformer method options] (m/-transformer map-schema transformer method options))
(-walk [this walker path options] (m/-walk-entries map-schema walker path options))
(-properties [_] properties)
(-options [_] options)
(-children [_] (m/-entry-children entry-parser))
(-parent [_] parent)
(-form [_] (m/-form map-schema))
m/EntrySchema
(-entries [_] (m/-entry-entries entry-parser))
(-entry-parser [_] entry-parser)
m/Cached
(-cache [_] cache)
m/LensSchema
(-keep [_] true)
(-get [this key default] (m/-get-entries this key default))
(-set [this key value] (m/-set-entries this key value))))))))
the main thing is when malli creates the schema (using -into-schema
you take the provided children and create an underlying :map
schema
map-schema (m/schema (into [:map] children))
there may be a much simpler way to do this, I'm not an expert on this, just figuring things out by reading the source code of malli.core
and you can try it with:
(m/validate
(m/schema [:entity-map [:x :int]]
{:registry (assoc (m/default-schemas) :entity-map (-entity-map-schema))})
(d/entity db [:some/id-prop 5]))
This gives a very good head start. I was also thinking on the same lines of copying map schema and hacking through it.
Thanks again @U051V5LLP!!!
sure thing! I'm still learning myself, so would be curious what you come up with ๐
Would it help if the malli.core/-map-schema
took an extra option for the predicate? e.g. on could just do:
(def EntityMap (m/-map-schema {:pred entity?}))
(m/validate EntityMap ...)
Malli is intended to be extendable, so all IntoSchema
s are created using functions and itโs a easy & non-breaking change to add new options ๐
Thanks for the suggestion Tommi. I will definitely look into implementing your suggestion and when satisfied, raise a PR ๐
@U055NJ5CC Raised this https://github.com/metosin/malli/pull/767 per your suggestion ๐