This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-11-25
Channels
- # aleph (2)
- # announcements (7)
- # babashka (6)
- # beginners (53)
- # calva (17)
- # cider (5)
- # clj-kondo (137)
- # cljs-dev (19)
- # cljsrn (14)
- # clojure (74)
- # clojure-conj (9)
- # clojure-europe (13)
- # clojure-houston (1)
- # clojure-italy (16)
- # clojure-nl (21)
- # clojure-spec (3)
- # clojure-uk (9)
- # clojuredesign-podcast (24)
- # clojurescript (85)
- # cursive (11)
- # datomic (28)
- # duct (3)
- # emacs (6)
- # figwheel-main (1)
- # fulcro (68)
- # graalvm (19)
- # graphql (3)
- # joker (32)
- # kaocha (10)
- # lambdaisland (1)
- # malli (50)
- # off-topic (13)
- # other-languages (7)
- # pathom (2)
- # pedestal (14)
- # re-frame (53)
- # reitit (8)
- # shadow-cljs (57)
- # specter (2)
so what happens when you use mt/transformer
to combine two existing transformers that have an encoder/decoder for same schema name?
seems to me that the last encoder/decoder function wins
so if you have a modifying transformer like strip-extra-keys-transformer
and someone else defines a transformer for :map
then one of them doesn’t work, if I am not mistaken
chain?
is this some new branch?
should I try to tamper with -transformer
function to achieve a modifying effect
It'd be reasonably easy to move the ->interceptor
function in to have it compose if there's already existing transformers
@ikitommi it might be worth having it compose with both :enter
and :leave
steps
you have a comment block at the top there
I just noticed that! Thanks!
https://github.com/metosin/malli/pull/122/files#diff-f4026c83e07e6f542344d5945d310607R12
So basically on the transformer
call where it calls ->interceptor
- you could move that reduce internally and then later transformers in & options
could just compose
maybe schema seems to be reporting wrong name in error message
.. about composing the transformers. What should happen when there are multiple transformers for same key? 1. last one wins (current) 2. all transformers with different name get chained 3. all get chained
(mt/transformer mt/json-transformer mt/json-transformer)
1. normal json
2. normal json
3. json + json(mt/transformer {:decoders {:map keywordize-keys}} mt/strip-extra-keys-transformer)
1. strip-keys wins
2. both
3. both@ikitommi I wouldn't do unique based off of name - I think for people unfamiliar with the implementation, you might not think that name matters much. Someone might write their own :json
that they also compose with the built in json
We could do all unique functions though
(mt/transformer {:decoders {:map keywordize-keys}} {:decoders {:map upper-case-keys})
1. upper-case wins
2. upper-case wins
3. bothI think both would be most useful
then you can write things like (mt/transformer keywords-as-strings capitalize-keywords)
(I could even see utility libraries existing with tons of tiny compositions of common transformer needs)
Also, I actually take back my comment on using unique functions
I'd say let the user compose things however they want
@ikitommi if you'd like I can add that functionality to my interceptor PR
I almost commented on GitHub but not sure where this thought would actually fit, I started pondering that what if the data given to interceptor would be a zipper like navigation cursor instead? This would actually allow the interceptor to walk up/down/left/right the data structure when needed, without "bind to parent to get access" kind of tricks.
Personally I prefer the interceptor pattern as a balance of simplicity, power, and because it's common in other libraries in the ecosystem. The cursor is definitely much much much more powerful, but building it will be non-trivial. Specifically, the way schema expansion currently happens is sort of a pre-walk - so a child doesn't even have reference to its parent because when the child is instantiated the parent doesn't even exist yet.
The other thing of note is that right now all of the traversal / introspection of the schema happens at compile time (or, at encoder
/ decoder
) time. I'm not familiar enough with zippers to think through how mapping the functions produced by the zipper could then be composed into a transformer
But I disagree on that sentiment of simplicity, as I don't see it as simple for any other than the simple use case - this parent awareness being a very good example of a sudden trickery situation, esp. with multi schemas where the parent doesn't necessarily dictate which child there is. It is always possible everyone's gotten things wrong so far... 🙂
It absolutely is!
I agree with you 100%
Because the schema's are data, we at least have the escape hatch of compiling a different schema
But that feels "dirty" to me - not sure why... maybe bad habits from spec
I've never used spec beyond tutorials tbh, I disliked its global registry and nested specs too much.
Lucky you 😉
But anyway, it definitely is a concern that it would probably be really slow (in relation to rest of malli)
The tooling story for spec is pretty cool. Definitely something I intend to port over to malli once things stabilize a bit
(>defn- wrap-vec
"Wraps the given target into a vector. If its already in a sequence, it will
be converted to a vector. If its a vector it will return itself. If its a value
it will be inserted into a vector"
[item]
[any? => (s/coll-of any? :kind vector?)]
(cond
(vector? item) item
(seq? item) (into [] item)
:else [item]))
That kind of inline annotation + optional checks is pretty useful
optional instrumentation I should say
I would prefer the plumatic schema fn syntax:
(m/defn plus :- int?
[x :- int?, y :- int?]
(+ x y))
@ikitommi interesting, why the preference? You like the type annotations right next to the variable name?
I can likely make both valid. I'll probably just have different namespaces that you can import from