This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-12-11
Channels
- # adventofcode (31)
- # announcements (6)
- # babashka (5)
- # beginners (93)
- # calva (15)
- # cider (20)
- # cljs-dev (16)
- # clojure (159)
- # clojure-berlin (1)
- # clojure-dev (5)
- # clojure-europe (9)
- # clojure-italy (9)
- # clojure-losangeles (2)
- # clojure-nl (26)
- # clojure-spec (7)
- # clojure-uk (33)
- # clojurescript (54)
- # clojutre (5)
- # cursive (20)
- # datomic (23)
- # emacs (19)
- # events (1)
- # expound (1)
- # figwheel-main (1)
- # fulcro (104)
- # hyperfiddle (1)
- # jobs (1)
- # luminus (10)
- # malli (59)
- # nrepl (1)
- # off-topic (11)
- # pathom (5)
- # planck (15)
- # reagent (13)
- # reitit (8)
- # rewrite-clj (10)
- # ring-swagger (3)
- # shadow-cljs (129)
- # tools-deps (46)
- # xtdb (14)
- # yada (1)
Checked the code., the build-transformer
doesn’t work correctly. I think the same problem is with all sequential schemas: the chain in :leave
shoud be in reverse order, so first apply the (child) value-transformers, then keys and last the map. This way, when changing the keys in :leave
, it’s the last thing that happens.
Also, all the three type of transformers should be created outside of the build-transformer
fn. Current impl creates all three two times (both in enter & leave) causing potential state-bugs with -value-transformer
impls as the enter & leave have different instances attached to them.
After that, this is the way to rename keys locally on encode:
(m/encode
[:map
[:foo [:map
[:foo int?]
[:bar int?]]]
[:bar int?]]
{:foo {:foo 2 :bar 1} :bar 3}
(transformer
{:encoders {'int? (constantly inc)
:map (constantly {:leave #(set/rename-keys % {:foo :oof :bar :rab})})}}))
; => {:oof {:oof 3, :rab 2}, :rab 4}
after the upcoming interceptor :compile
, will reduce to:
(m/encode
[:map
[:foo [:map
[:foo int?]
[:bar int?]]]
[:bar int?]]
{:foo {:foo 2 :bar 1} :bar 3}
(transformer
{:encoders {'int? inc
:map {:leave #(set/rename-keys % {:foo :oof :bar :rab})}}}))
; => {:oof {:oof 3, :rab 2}, :rab 4}
which will, I hope, solve your case @rschmukler elegantly enough?
would be interesting to see how malli would work on the dev-tooling space. Related to https://www.reddit.com/r/Clojure/comments/e95pr5/data_structure_shape_hints_and_intellisense/
@ikitommi nice! Good catch on build-transformer
being called twice and its impact on local state! Changing the order of the chains is also perfect - that'll make it much more like a postwalk on leave
@ikitommi I've got the first prototype of my defn-spec
/ ghostwheel clone. For now I'm doing it as a separate project (called aave
). Will be releasing a first version shortly
The syntax is abstractable though, so you can use schema style too if you want. Things that it currently supports are purity detection, configurable hooks for input and output validation at both compile time and run time. Next up is benchmarking.
I also thought it'd be cool to be able to do something like
(defn add-name-key
[a]
[:map => (+ a [:name string?])]
(assoc a :name "Bob")
Where + symbol
basically expands out to "merge schema from parameter a
"Might be overkill haha - but it could enable deep compile-time tracking of types
@rschmukler sounds awesome, and what a name! 👻
😄 I'm glad you like it
ok, let's try this again. How would you write a function that returns a malli spec to test if a string is of length n?
(defn fixed-length? [n]
[:and 'string? [:fn `(~'fn [~'val] (~'= ~n (~'count ~'val)))]]
)
that gives me:
(preds/fixed-length? 10)
=> [:and string? [:fn (fn [val] (= 10 (count val)))]]
@beders Do you need it to all be quoted? Malli should take care of that for you. if not, you can just do:
(defn fixed-length? [n]
[:and string? [:fn #(= n (count %)]])
but my code doesn't look very nice. Lots of quoting to prevent backtick from full name resolution
(defn fixed-length? [n]
[:and string? [:fn #(= n (count %))]])
=> #'sql-to-malli.integration/fixed-length?
(edn/write-string (fixed-length? 10))
=>
"[:and string? [:fn #object[sql_to_malli.integration$fixed_length_QMARK_$fn__10416 0x576cee60 \"sql_to_malli.integration$fixed_length_QMARK_$fn__10416@576cee60\"]]]"
Ah I suppose that's true!
can you do
(defn fixed-length? [n]
[:and 'string? [:fn `(fn [val] (= ~n (~'count val)))]]
)
(fixed-length? 10)
=> [:and string? [:fn (clojure.core/fn [clojure.core/val] (clojure.core/= 10 (count clojure.core/val)))]]
But you need your schema to be serializable?
I'd consider adding it to your registry using fn-schema
@ikitommi he needs to get the 10 in there though
but with a custom registry, you could just do [:and 'string? [:fixed-length 10]]
I was hoping I could run this on a database schema, copy the resulting malli schemas and then run with them
Oh you know
you might be able to do
Nope, never mind 😄
JSON Schema defines extra attributes for numbers, strings and arrays. Malli could have those too?
[string? {:min 10, :max 10}]
Also, malli schema properties should be defined with malli schemas to get nice docs & validation of those too.
@beders if the runtime dependwncy would be ok, you could also just use the Schema Var instead of registry:
[my-lib.schemas/fixed-lenght 10]