malli

https://github.com/metosin/malli :malli:
ikitommi 2020-11-17T08:45:06.085600Z

there are some gaps in the malli->clj-kondo integration, any insights welcome: https://github.com/metosin/malli/blob/cde74871ee5edc1525344f7a6e62d54fb1b00f5b/src/malli/clj_kondo.cljc. marked with ;;??

ikitommi 2020-11-17T08:45:34.086200Z

currently:

(require '[malli.clj-kondo :as mc])

(mc/transform
  [:map
   [:id string?]
   [:tags {:optional true} [:set keyword?]]
   [:address
    [:map
     [:street string?]
     [:city string?]
     [:zip {:optional true} int?]
     [:lonlat [:tuple double? double?]]]]])
;{:op :keys
; :opt {:tags :set}
; :req {:id :string
;       :address {:op :keys
;                 :opt {:zip :int}
;                 :req {:street :string
;                       :city :string
;                       :lonlat [:double :double]}}}}

ikitommi 2020-11-17T08:51:35.087800Z

btw, would be great if clj-kondo supported :min and :max for numbers & collections. nice demo about “more than types”, something like:

(ms/defn times :- :int
  "times"
  [x :- [:int {:min 3}]]
  (* x x))

(times 2)
;; ^:--- clj-kondo error of "number should be at least 3"

borkdude 2020-11-17T09:25:49.088700Z

Don't know if this a common enough problem in function calls. I haven't encountered this much I think. If there's a domain specific need to check this, one can also write a hook

ikitommi 2020-11-17T09:32:06.092200Z

ok. just wondering as clj-kondo already supports map-op-syntax, so if :int could be defined as {:op :int}, it would allow adding easily new keys that would be easy to check, e.g. malli could emit {:opt :int, :min 3} from the example. Not sure how useful that would be, but: • number min & max might be easy to implement on clj-kondo side? • would be a great demo, as you can’t easily present these with simple typed langs liike Java

ikitommi 2020-11-17T09:32:54.092700Z

but, I don’t need this for real, just thinking aloud about a kick-ass demo 🙂

borkdude 2020-11-17T09:33:26.093200Z

it has :pos-int and :nat-int which map to the clojure predicates. it basically only has that which exists as predicates in clojure 1.9+

borkdude 2020-11-17T09:36:20.094700Z

@ikitommi Feel free to try out things with the clj-kondo type system. You can build a custom clj-kondo for your demo possibly

borkdude 2020-11-17T09:36:33.095Z

it's all in clj-kondo.impl.types

ikitommi 2020-11-17T09:36:51.095300Z

thanks, might give it a shot.

borkdude 2020-11-17T09:42:51.096700Z

@ikitommi Ah, I can see why your approach might be problematic: https://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/types.clj#L157-L163 So the literal value is mapped to a type tag. And then during checking that is resolved very cheaply, not executing any predicates, but just checking a keyword identity or a super simple graph, e.g. a pos-int is also an int

1👀
borkdude 2020-11-17T09:44:17.097200Z

so the literal value is erased as it were

Hankstenberg 2020-11-17T18:47:55.102700Z

Hi guys, just getting my feet wet with malli. Quick question: when I try to transform a map to JSON-Schema, all the map's keywords are still Clojure keywords and thus invalid syntax in JSON-Schema. Sure, I could post-process it, but is this on purpose? What's the best way to get proper JSON-Schema?

ikitommi 2020-11-17T19:03:43.103700Z

@marcus.poparcus I think it would be better to emit strings directly. PR Welcome.