Fork me on GitHub
#malli
<
2021-09-26
>
Carlo02:09:51

using malli/core, is there a way to spec a plus function over positive numbers, asserting that that the result is >= of any of the arguments?

Carlo10:09:32

the closest thing I saw is using the :fn spec to relate the arguments, but I'm not sure how to involve the result of the function

lsenjov11:09:20

I’m not sure you actually can, off the top of my head. You could use pre-post maps in core clojure to test these contracts

lsenjov11:09:34

(If there’s a way to do it I’m sure someone will have a peek when the working week starts)

ikitommi11:09:29

@UA7E6DU04 no, there is no :fn, like there is for spec:

(s/fdef ranged-rand
  :args (s/and (s/cat :start int? :end int?)
               #(< (:start %) (:end %)))
  :ret int?
  :fn (s/and #(>= (:ret %) (-> % :args :start))
             #(< (:ret %) (-> % :args :end))))
, but I don’t see any reason why it would not be supported.

ikitommi11:09:31

please write an Issue, so it’s on the backlog.

ikitommi11:09:34

also. there is silly assert inside malli.core that the :input (`:args` in spec) need to be a :cat, so :and doesn’t work. Easy to fix.

ikitommi11:09:15

ast-options for eager references, this:

[:and
 {:registry {::a ::b
             ::b ::c
             ::c [:schema pos-int?]}}
 ::a ::b ::c]
ast options: 1️⃣ current:
{:type :and,
 :children [{:type ::m/schema, :value ::a}
            {:type ::m/schema, :value ::b}
            {:type ::m/schema, :value ::c}]
 :registry {::a {:type ::m/schema, :value ::b}
            ::b {:type ::m/schema, :value ::c}
            ::c {:type :schema, :child {:type 'pos-int?}}}}
2️⃣ less noicy:
{:type :and,
 :children [{:type ::a}
            {:type ::b}
            {:type ::c}]
 :registry {::a {:type ::b}
            ::b {:type ::c}
            ::c {:type :schema
                 :child {:type 'pos-int?}}}}
3️⃣ compact:
{:type :and,
 :children [::a ::b ::c]
 :registry {::a ::b
            ::b ::c
            ::c {:type :schema
                 :child {:type 'pos-int?}}}}

Ben Sless11:09:07

3 looks best

ikitommi13:09:08

I think 3 is also the fastest, short-circuiting to lookup instead of walking more maps before the lookup. Pushed the registry into it's own key, it's also faster to use (one map lookup less) and looks better. So, ast is map with :type, optionally :properties and :registry. Plus any keys Schema wasn't to lift there. There are few comventions with helpers: • no child's -> nothing added • one child -> :child • many childs -> :children • same, but not schemas, just values (e.g. [:> 1], [:enum "small" "large"] -> :value and :values • entries -> :keys with maps with :value, optionally :prooerties and :order ... but, could have anything, like :=> has :input & :output

ikitommi13:09:08

I think 3 is also the fastest, short-circuiting to lookup instead of walking more maps before the lookup. Pushed the registry into it's own key, it's also faster to use (one map lookup less) and looks better. So, ast is map with :type, optionally :properties and :registry. Plus any keys Schema wasn't to lift there. There are few comventions with helpers: • no child's -> nothing added • one child -> :child • many childs -> :children • same, but not schemas, just values (e.g. [:> 1], [:enum "small" "large"] -> :value and :values • entries -> :keys with maps with :value, optionally :prooerties and :order ... but, could have anything, like :=> has :input & :output