This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-08-14
Channels
- # announcements (31)
- # babashka (9)
- # beginners (4)
- # calva (67)
- # cider (6)
- # clj-yaml (10)
- # clojure (105)
- # clojure-austin (8)
- # clojure-bay-area (1)
- # clojure-europe (12)
- # clojure-germany (3)
- # clojure-nl (1)
- # clojure-norway (7)
- # clojure-uk (2)
- # clojurescript (5)
- # core-logic (4)
- # data-science (29)
- # datomic (6)
- # dev-tooling (5)
- # emacs (3)
- # hyperfiddle (22)
- # introduce-yourself (4)
- # lsp (8)
- # malli (10)
- # off-topic (8)
- # pathom (74)
- # polylith (39)
- # practicalli (1)
- # reitit (3)
- # shadow-cljs (2)
- # spacemacs (3)
- # squint (4)
- # tools-deps (4)
Is there a way to get the type information in regard to a function?
(defn square [x] (* x x))
(m/=> square [:=> {:registry {:a :int}} [:cat :a] nat-int?])
How do I “grab” input/output for square
as I’d like to use it elsewhere?I got as far as (m/function-schemas)
, but I’d like to ascertain the input/outputs for square
You can ask m/childre
n on the schema or call m/ast
on it and use the named keys on the result (I recall :input
& :output
.
I’m using Malli to generate data for Pathom, in particular the inputs/outputs in this case. So what I’m really interested in is the registry keywords.
To look-up square
in the map, this works, but I’m guessing there’s a better “trick”?
(get (get (m/function-schemas) (symbol (namespace `square))) 'square)
Does someone have good arguments for or against the correctness on how :or
is decoded now: https://github.com/metosin/malli/issues/910#issuecomment-1676768588
I would like to comment but haven’t been affected by this so cannot without more context. if you provide context, I’ll try to add my opinion
my 2 cents I would avoid #1 , because it's not very nice mathematically
(def T (mt/transformer {:name :math}))
(def S1 [:map {:closed true, :decode/math #(assoc % :b 'bad-input)}
[:a :int]
[:b :int]])
(def S2 [:map {:closed true, :decode/math #(assoc % :a 'bad-input)}
[:a :int]
[:b :int]])
(def I {:a 4, :b 5})
(m/decode S1 I T) ;=> {:a 4, :b bad-input}
(m/decode S2 I T) ;= {:b 4, :a bad-input}
(m/decode [:or S1 S2] I T) ;=> {:a 4, :b 5}
S1 would never validate value I transformed
S2 would never validate value I transformed
Yet the S1 ∪ S2 validates value I ‘transformed’ by virtue of the ‘transformation’ being a no-op
I may have a use case that's too contrived to explain, but in theory it could hit this, (in practice probably not), and #1 would be the wrong choice.
I like both #2 and #3, my intuition slightly prefers #3. As a side note, could you just produce an error, is that a 4th choice.
In stricter functional implementations of these 'bijection-like' transformations, when you transform from type A into type B, the return value is either (1) of type B or (2) an error of some kind, the untransformed values are bit dangerous, as it can accidentally get validated as B, when in fact untransformed values of type A just look a bit like B in pathological cases, if that makes sense .Thanks @U0J3J79FE for the long answer! Few comments:
• goal of decode is to produce valid values, so all cases where decode breaks it are kinda wrong
• I agree on 1 being wrong
• m/coerce
does both decode & validate
• I'm also leaning also towards 3 (today)