Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge map-of into map #52

Merged
merged 2 commits into from Sep 1, 2019
Merged

Merge map-of into map #52

merged 2 commits into from Sep 1, 2019

Conversation

jeans11
Copy link
Contributor

@jeans11 jeans11 commented Aug 29, 2019

#43

(m/validate [:map keyword? int?] {:x 1 :y 2})
;; true

(m/validate
  [:map
    [:x string?]
    [[:opt :y] int?]
    [keyword? [:vector int?]]]
  {:x "x"
   :z [1 2 3]})
;; true

(m/validate [:map [:x int?] [keyword? string?]] {:x 1 :z 2})
;; false

Copy link
Member

@ikitommi ikitommi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! Looking good, few comments to make it even better :)

[entry]
(-> entry meta :pred-key?))

(defn- -only-map-of?
Copy link
Member

@ikitommi ikitommi Aug 29, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think less is more: map already has special syntax (in form of map-entries are represented as a vector), I think we could force all entries to be represented this way, so special syntax for only map-of. The code would be much simpler too, I believe.

;; illegal
[:map int? int?]

;; ok
[:map [int? int?]]

what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea!

(let [valid? (-validator value)
default (boolean optional)]
(fn [m] (if-let [map-entry (find m key)] (valid? (val map-entry)) default))))
(fn [m]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's not push any code from compile time into validation time if possible. Hre, validators vector could contain first the normal key validators and the the extra validators. Same goes for -explainer and -transformer methods, all on the hot perf path.

There is a small perf regression test suite if you want to peek how this would effect perf. My guess it's 2-5x times slower than before, see
https://github.com/metosin/malli/blob/master/perf/malli/perf_test.cljc#L244

[:map
[:x string?]
[[:opt :y] int?]
[keyword? int?]])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there should be a test that for multiple predicate keys too. Schema explicitly only allows one extra key per map, I think we might not need that restriction.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, was thinking Plumatic schema, which has the limitation - just one predicate key per map

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allow something like that?

(m/schema
  [:map
    [keyword? int?]
    [keyword? string?]])

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not. That can already be defined as:

[:map
  [keyword? [:or int? string?]]

... and this would cause trouble when later doing tools to merge maps and removing keyword? key might or might not remove all keys. Same actually applies to normal keys, this should be illegal:

[:map [:x int?] [:x string?]]

@ikitommi
Copy link
Member

ikitommi commented Sep 1, 2019

Thanks! I'll merge this in and will check the perf & think about corner cases.

@ikitommi ikitommi merged commit 7c0d7ac into metosin:master Sep 1, 2019
@ikitommi
Copy link
Member

ikitommi commented Sep 1, 2019

perf regressed for validation of [:map [:x int?] [:y boolean?]] from 17ns to 110ns (6x). I need this for the generator branch, so will do some perf tuning on top of this.

@ikitommi
Copy link
Member

ikitommi commented Sep 1, 2019

There is actually ambiguity rule here:

Given a schema:

[:map
  [:a int?]
  [:b string?]
  [::id string?]

One could have binded the ::id into a defined value via a registry, so it's a valid schema. The code in this PR doesn't resolve ::id as a schema as the code doesn't pass options into the -valid-schema? function. That's a bug. If that is fixed, the ::id would be resolved into a schema and it's value is used instead ::id as a key => there is no way to represent key ::id in the map, which is not acceptable. Also, few commits ago, I made the IntoSchema work with malli.core/schema too, so:

(m/schema :tuple)
; :tuple

=> :tuple would be illegal key in any map.

Will remove the changes and put the commits aside until resolved. Need to think this over.

@ikitommi
Copy link
Member

ikitommi commented Sep 1, 2019

Master is reset back before this, and these changed are stored in branch https://github.com/metosin/malli/tree/map-of-with-map

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants