This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-03-25
Channels
- # aleph (9)
- # announcements (2)
- # babashka (32)
- # babashka-sci-dev (72)
- # beginners (77)
- # calva (1)
- # cider (3)
- # clj-kondo (19)
- # clojure (61)
- # clojure-brasil (13)
- # clojure-europe (25)
- # clojure-italy (1)
- # clojure-nl (2)
- # clojure-norway (27)
- # clojure-uk (23)
- # clojuredesign-podcast (6)
- # clojurescript (12)
- # conjure (2)
- # core-typed (3)
- # cursive (6)
- # datalevin (2)
- # datomic (13)
- # emacs (9)
- # events (19)
- # fulcro (6)
- # graphql (11)
- # gratitude (2)
- # helix (3)
- # honeysql (16)
- # jobs (1)
- # lsp (89)
- # malli (33)
- # meander (14)
- # off-topic (87)
- # pathom (4)
- # polylith (7)
- # portal (4)
- # practicalli (1)
- # rdf (6)
- # reagent (2)
- # releases (8)
- # remote-jobs (1)
- # shadow-cljs (59)
- # sql (8)
- # tools-deps (14)
- # xtdb (18)
I recently added static type checking for malli schemas to Typed Clojure, here's a writeup on how to do it https://github.com/typedclojure/typedclojure/tree/main/example-projects/malli-type-providers
Oh Yeah!
Cool! What is the tooling like nowadays? Does it require REPL (so it is one the same classpath as the running app) or could it be integrated into clojure-lsp?
@UK0810AQ2 it's a https://github.com/typedclojure/typedclojure/blob/4818f27a4661262b0d8268a6b00bd0363b02dba0/typed/malli/src/typed/malli/parse_type.clj#L196 right now for custom schemas, a big case
. Could probably be a multimethod, do you have an example of a custom schema to help me understand the design space? And custom registries, I'm not sure how far it gets me, but I use m/-deref
when I find a :ref
. That should be enough?
@U061V0GG2 requires a REPL since it macroexpands code.
Maybe if we create a custom macro rule for every macro in clojure.core we can think of a clojure-lsp version.
A good example of custom schemas would be for time types, such as https://github.com/metosin/malli/pull/545 Similarly for other iterop-y parse-y things, like valid URIs
ok, I think we need something like (defmethod malli->Type :local-date [_] 'java.time.LocalTime)
.
So if those schemas had a way to query their backing class it would make it easier to participate in typed.clojure?
No, but I could petition for something like "simple class schema" which could back various boring data classes
Can you think of any custom registry case that might be problematic? I just call m/deref
to convert the entire schema eagerly.
ah yep, I handle those https://github.com/typedclojure/typedclojure/blob/4818f27a4661262b0d8268a6b00bd0363b02dba0/typed/malli/src/typed/malli/parse_type.clj#L236
probably would need a custom m/type
dispatch in the (future) malli->Type
multimethod.
another way these simple schemas could be automated is if Typed Clojure could know the var backing the :pred
. eg., pos-int? here
welcome
, thanks @meditans for the idea.
Using it to create pretty checker:
(require '[malli.instrument :as mi])
(require '[malli.dev.pretty :as pretty])
(defn check
"check that emits pretty results"
([] (check nil))
([options] ((pretty/prettifier ::check "Check Error" (fn [] (mi/check)) options))))
Dummy pretty printer for ::check:
(defmethod v/-format ::check [_ _ results printer]
{:body (->> (for [[f error] results
:let [{:keys [schema errors]} error
explanation (-> errors first :check :malli.generator/explain-output)]]
[:group
(pretty/-block "When calling:" (v/-visit (-> errors first :check :smallest first (conj f)) printer) printer) :break :break
(pretty/-block "We get:" (v/-visit (:value explanation) printer) printer) :break :break
(pretty/-block "The problem is that:" (v/-visit (me/humanize explanation) printer) printer) :break :break
(pretty/-block "Schema:" (v/-visit schema printer) printer)])
(interpose [:group (v/-color :title-dark (apply str (take 30 (repeat "-"))) printer) :break :break])
(into [:group]))})
in action:
(check)
the actual printer is silly here, should separate the input & output schema problems, looking forward to seeing what you @meditans cooked up for this.
but, the core-lib support pretty-anything now. the helper looks like:
(defn prettifier [type title f options]
(let [printer (assoc (or (::printer options) (assoc (-printer) :width 60)) :title title)
actor (::actor options reporter)]
(fn [& args] (when-let [res (apply f args)] ((actor printer) type res) res))))
I am in fact still at a prototype stage re: precise messages (and I mainly produce hiccup to pass to #portal, which I'm trying to turn in my repl for visualization). But I'll definitely try this out and upstream improvements if I end up making them for myself. I have to say, ideally for me, this prettified error message would be more usable in the form of a data structure (from which I can generate hiccup). But I can as well keep producing it myself from the error!