Hi folks. I think I found a strange behavior on the :map-of type schema.
Example:
(sm/decode [:map-of :string :string] (d/ordered-map "a" "b") sm/json-transformer)
=>> {"a" "b"}
But I expect it to preserve the type of the map:
(sm/decode [:map-of :string :string] (d/ordered-map "a" "b") sm/json-transformer)
=>> #linked/map [["a" "b"]]I think the problem is on the -transform-map-keys. I have changed it to:
(defn -transform-map-keys
([f]
#(cond->> % (map? %) (into (empty %) (map (fn [[k v]] [(f k) v])))))
([ks f]
#(cond->> % (map? %) (into (empty %) (map (fn [[k v]] [(cond-> k (contains? ks k) f) v]))))))
And now it preserves the type.
Is this ok for a PR?I'm also extracted the xform to "compile phase":
(defn -transform-map-keys
([f]
(let [xform (map (fn [[k v]] [(f k) v]))]
#(cond->> % (map? %) (into (empty %) xform))))
([ks f]
(let [xform (map (fn [[k v]] [(cond-> k (contains? ks k) f) v]))]
#(cond->> % (map? %) (into (empty %) xform)))))
That removes the need to create it each time the decode-fn is executed
yeah I think that change makes sense
PR would be appreciated, but please add new test cases as well!
Is OK for adding an library for ordered map? for test only obviously
this will allow check that other map type is preserved
is clojure.core/sorted-map not enough?
otherwise, adding libs to the test deps is fine tho
I will try to do it with sorted-map
I didn't put any description on PR, because the context is already here
Pushed an additonal commit with PR feedback changes for easy review. If it is all ok, this can be merged with "Squash" option that combined both commit in one.
oops, did a non-squash merge before I saw your message here
but that's fine, we like history
perfect, no problem at all thanks!
I figured out this same change will apply to :map as well, so I'm writing some more test cases
nice 😄
Is there a way to define a :set schema that requires some item in the set to match the schema but not require that every item in the set matches the schema? I suspect I need to resort to a :fn schema for this, but it's not clear to me how to do that when using a local registry, and a pure data solution would be nicer anyway.
I don't think so. If the required thing is a value, this upcoming PR would be able to handle it via [:and [:set :any] [:has VALUE]]. https://github.com/metosin/malli/pull/1161/files
At times I've wanted a :fn schema that takes options so you can use a local registry. Like [:fn+options (fn [options] (let [p (m/validator ::local options)] #(some p %)))].
I don't think this exists yet.
Looks cool but unfortunately doesn't solve my problem since I don't have a value to compare against but rather a schema. I agree about the fn+options idea, it would be nice to be able to access the registry via a function param.
should be possible with m/-proxy-schema. I can sketch it up if you'd like.
Sure, if you don't mind. I was able to work out the :fn schema to do what I want so it's not a big issue